breakpoint
|
@ -152,7 +152,7 @@ Transform:
|
||||||
m_PrefabInstance: {fileID: 0}
|
m_PrefabInstance: {fileID: 0}
|
||||||
m_PrefabAsset: {fileID: 0}
|
m_PrefabAsset: {fileID: 0}
|
||||||
m_GameObject: {fileID: 2316171592450128199}
|
m_GameObject: {fileID: 2316171592450128199}
|
||||||
m_LocalRotation: {x: 0.70710665, y: 0.70710695, z: 0.00000033102063, w: -0.00000019861227}
|
m_LocalRotation: {x: 0.70710665, y: 0.70710695, z: 0.00000033102063, w: -0.0000001986123}
|
||||||
m_LocalPosition: {x: 0.79999834, y: 1.099999, z: 0}
|
m_LocalPosition: {x: 0.79999834, y: 1.099999, z: 0}
|
||||||
m_LocalScale: {x: 1, y: 1, z: 1}
|
m_LocalScale: {x: 1, y: 1, z: 1}
|
||||||
m_ConstrainProportionsScale: 0
|
m_ConstrainProportionsScale: 0
|
||||||
|
@ -233,7 +233,7 @@ ParentConstraint:
|
||||||
m_TranslationOffsets:
|
m_TranslationOffsets:
|
||||||
- {x: 0, y: 0, z: 0}
|
- {x: 0, y: 0, z: 0}
|
||||||
m_RotationOffsets:
|
m_RotationOffsets:
|
||||||
- {x: -89.97203, y: 0, z: -180}
|
- {x: -89.980225, y: 0, z: -180}
|
||||||
m_AffectTranslationX: 1
|
m_AffectTranslationX: 1
|
||||||
m_AffectTranslationY: 1
|
m_AffectTranslationY: 1
|
||||||
m_AffectTranslationZ: 1
|
m_AffectTranslationZ: 1
|
||||||
|
@ -897,6 +897,17 @@ MonoBehaviour:
|
||||||
m_Script: {fileID: 11500000, guid: 68aea78d5db589148aa74a9b54d6ac31, type: 3}
|
m_Script: {fileID: 11500000, guid: 68aea78d5db589148aa74a9b54d6ac31, type: 3}
|
||||||
m_Name:
|
m_Name:
|
||||||
m_EditorClassIdentifier:
|
m_EditorClassIdentifier:
|
||||||
|
netClient:
|
||||||
|
rid: 5474080454516408331
|
||||||
|
netProvider:
|
||||||
|
rid: 5474080454516408332
|
||||||
|
references:
|
||||||
|
version: 2
|
||||||
|
RefIds:
|
||||||
|
- rid: 5474080454516408331
|
||||||
|
type: {class: GDNetServiceSingleton, ns: BITKit, asm: BITKit.Extension.GameDesigner}
|
||||||
|
- rid: 5474080454516408332
|
||||||
|
type: {class: GDNetServiceSingleton, ns: BITKit, asm: BITKit.Extension.GameDesigner}
|
||||||
--- !u!114 &3044462450513940359
|
--- !u!114 &3044462450513940359
|
||||||
MonoBehaviour:
|
MonoBehaviour:
|
||||||
m_ObjectHideFlags: 0
|
m_ObjectHideFlags: 0
|
||||||
|
@ -1401,7 +1412,7 @@ Transform:
|
||||||
m_PrefabAsset: {fileID: 0}
|
m_PrefabAsset: {fileID: 0}
|
||||||
m_GameObject: {fileID: 7147149369621539321}
|
m_GameObject: {fileID: 7147149369621539321}
|
||||||
m_LocalRotation: {x: -0, y: -0, z: -0, w: 1}
|
m_LocalRotation: {x: -0, y: -0, z: -0, w: 1}
|
||||||
m_LocalPosition: {x: -0.00000011920929, y: 0.9000001, z: -0.00000020647656}
|
m_LocalPosition: {x: -0.00000007868051, y: 0.9000001, z: -0.00000011920929}
|
||||||
m_LocalScale: {x: 1, y: 1, z: 1}
|
m_LocalScale: {x: 1, y: 1, z: 1}
|
||||||
m_ConstrainProportionsScale: 0
|
m_ConstrainProportionsScale: 0
|
||||||
m_Children:
|
m_Children:
|
||||||
|
|
|
@ -1,89 +0,0 @@
|
||||||
%YAML 1.1
|
|
||||||
%TAG !u! tag:unity3d.com,2011:
|
|
||||||
--- !u!1 &8392035340861090216
|
|
||||||
GameObject:
|
|
||||||
m_ObjectHideFlags: 0
|
|
||||||
m_CorrespondingSourceObject: {fileID: 0}
|
|
||||||
m_PrefabInstance: {fileID: 0}
|
|
||||||
m_PrefabAsset: {fileID: 0}
|
|
||||||
serializedVersion: 6
|
|
||||||
m_Component:
|
|
||||||
- component: {fileID: 7599459500757629658}
|
|
||||||
- component: {fileID: 7546290009901106985}
|
|
||||||
- component: {fileID: 1634786267599951643}
|
|
||||||
m_Layer: 0
|
|
||||||
m_Name: BITNet
|
|
||||||
m_TagString: Untagged
|
|
||||||
m_Icon: {fileID: 2800000, guid: 9924c5997a91b6240b88431f1b30c68b, type: 3}
|
|
||||||
m_NavMeshLayer: 0
|
|
||||||
m_StaticEditorFlags: 0
|
|
||||||
m_IsActive: 1
|
|
||||||
--- !u!4 &7599459500757629658
|
|
||||||
Transform:
|
|
||||||
m_ObjectHideFlags: 0
|
|
||||||
m_CorrespondingSourceObject: {fileID: 0}
|
|
||||||
m_PrefabInstance: {fileID: 0}
|
|
||||||
m_PrefabAsset: {fileID: 0}
|
|
||||||
m_GameObject: {fileID: 8392035340861090216}
|
|
||||||
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: []
|
|
||||||
m_Father: {fileID: 0}
|
|
||||||
m_RootOrder: 0
|
|
||||||
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
|
|
||||||
--- !u!114 &7546290009901106985
|
|
||||||
MonoBehaviour:
|
|
||||||
m_ObjectHideFlags: 0
|
|
||||||
m_CorrespondingSourceObject: {fileID: 0}
|
|
||||||
m_PrefabInstance: {fileID: 0}
|
|
||||||
m_PrefabAsset: {fileID: 0}
|
|
||||||
m_GameObject: {fileID: 8392035340861090216}
|
|
||||||
m_Enabled: 1
|
|
||||||
m_EditorHideFlags: 0
|
|
||||||
m_Script: {fileID: 11500000, guid: f478b00e78634b04c8d5e2844ef94668, type: 3}
|
|
||||||
m_Name:
|
|
||||||
m_EditorClassIdentifier:
|
|
||||||
address: localhost
|
|
||||||
port: 27014
|
|
||||||
apiPort: 27013
|
|
||||||
webProvider:
|
|
||||||
rid: 5474080363716280323
|
|
||||||
clientProvider:
|
|
||||||
rid: 5474080363716280324
|
|
||||||
references:
|
|
||||||
version: 2
|
|
||||||
RefIds:
|
|
||||||
- rid: 5474080363716280323
|
|
||||||
type: {class: HttpClient, ns: BITKit.HttpNet, asm: BITKit}
|
|
||||||
- rid: 5474080363716280324
|
|
||||||
type: {class: FlibClientProvider, ns: BITFALL, asm: BITFALL}
|
|
||||||
data:
|
|
||||||
clientManager: {fileID: 1634786267599951643}
|
|
||||||
--- !u!114 &1634786267599951643
|
|
||||||
MonoBehaviour:
|
|
||||||
m_ObjectHideFlags: 0
|
|
||||||
m_CorrespondingSourceObject: {fileID: 0}
|
|
||||||
m_PrefabInstance: {fileID: 0}
|
|
||||||
m_PrefabAsset: {fileID: 0}
|
|
||||||
m_GameObject: {fileID: 8392035340861090216}
|
|
||||||
m_Enabled: 1
|
|
||||||
m_EditorHideFlags: 0
|
|
||||||
m_Script: {fileID: 11500000, guid: 43dd04617c9f105449b227e016c972a4, type: 3}
|
|
||||||
m_Name:
|
|
||||||
m_EditorClassIdentifier:
|
|
||||||
protocol: 0
|
|
||||||
ip: 127.0.0.1
|
|
||||||
port: 9543
|
|
||||||
localTest: 0
|
|
||||||
logMode: 1
|
|
||||||
debugRpc: 0
|
|
||||||
authorize: 0
|
|
||||||
startConnect: 0
|
|
||||||
md5CRC: 0
|
|
||||||
reconnectCount: 10
|
|
||||||
reconnectInterval: 2000
|
|
||||||
heartLimit: 5
|
|
||||||
heartInterval: 1000
|
|
||||||
dontDestroyOnLoad: 0
|
|
|
@ -1,55 +0,0 @@
|
||||||
%YAML 1.1
|
|
||||||
%TAG !u! tag:unity3d.com,2011:
|
|
||||||
--- !u!1 &6719114749252097002
|
|
||||||
GameObject:
|
|
||||||
m_ObjectHideFlags: 0
|
|
||||||
m_CorrespondingSourceObject: {fileID: 0}
|
|
||||||
m_PrefabInstance: {fileID: 0}
|
|
||||||
m_PrefabAsset: {fileID: 0}
|
|
||||||
serializedVersion: 6
|
|
||||||
m_Component:
|
|
||||||
- component: {fileID: 6175441137035486932}
|
|
||||||
- component: {fileID: 7284902202986547444}
|
|
||||||
m_Layer: 0
|
|
||||||
m_Name: BulletService
|
|
||||||
m_TagString: Untagged
|
|
||||||
m_Icon: {fileID: 0}
|
|
||||||
m_NavMeshLayer: 0
|
|
||||||
m_StaticEditorFlags: 0
|
|
||||||
m_IsActive: 1
|
|
||||||
--- !u!4 &6175441137035486932
|
|
||||||
Transform:
|
|
||||||
m_ObjectHideFlags: 0
|
|
||||||
m_CorrespondingSourceObject: {fileID: 0}
|
|
||||||
m_PrefabInstance: {fileID: 0}
|
|
||||||
m_PrefabAsset: {fileID: 0}
|
|
||||||
m_GameObject: {fileID: 6719114749252097002}
|
|
||||||
m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
|
|
||||||
m_LocalPosition: {x: 1.5131056, y: 1.0793136, z: 5.1427784}
|
|
||||||
m_LocalScale: {x: 1, y: 1, z: 1}
|
|
||||||
m_ConstrainProportionsScale: 0
|
|
||||||
m_Children: []
|
|
||||||
m_Father: {fileID: 0}
|
|
||||||
m_RootOrder: 0
|
|
||||||
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
|
|
||||||
--- !u!114 &7284902202986547444
|
|
||||||
MonoBehaviour:
|
|
||||||
m_ObjectHideFlags: 0
|
|
||||||
m_CorrespondingSourceObject: {fileID: 0}
|
|
||||||
m_PrefabInstance: {fileID: 0}
|
|
||||||
m_PrefabAsset: {fileID: 0}
|
|
||||||
m_GameObject: {fileID: 6719114749252097002}
|
|
||||||
m_Enabled: 1
|
|
||||||
m_EditorHideFlags: 0
|
|
||||||
m_Script: {fileID: 11500000, guid: 17af089f9db44e8449d71f65830fdd25, type: 3}
|
|
||||||
m_Name:
|
|
||||||
m_EditorClassIdentifier:
|
|
||||||
layerMask:
|
|
||||||
serializedVersion: 2
|
|
||||||
m_Bits: 513
|
|
||||||
defaultMaterial: {fileID: 11400000, guid: 6ce8f51b55ed1b84db162e849100dc10, type: 2}
|
|
||||||
pool:
|
|
||||||
prefab: {fileID: 2956281190107464547, guid: cd8502ee01a85944bbccb38128facc13,
|
|
||||||
type: 3}
|
|
||||||
root: {fileID: 6175441137035486932}
|
|
||||||
instances: []
|
|
|
@ -14,9 +14,12 @@ GameObject:
|
||||||
- component: {fileID: 5459949338997660565}
|
- component: {fileID: 5459949338997660565}
|
||||||
- component: {fileID: -2281902509228225294}
|
- component: {fileID: -2281902509228225294}
|
||||||
- component: {fileID: 4083894557606377552}
|
- component: {fileID: 4083894557606377552}
|
||||||
- component: {fileID: -3428271289843395767}
|
- component: {fileID: 2356180584613640822}
|
||||||
|
- component: {fileID: -3918555459250571244}
|
||||||
|
- component: {fileID: -31602009599847191}
|
||||||
|
- component: {fileID: 1510713985089303888}
|
||||||
m_Layer: 0
|
m_Layer: 0
|
||||||
m_Name: BITFramework
|
m_Name: Framework
|
||||||
m_TagString: Untagged
|
m_TagString: Untagged
|
||||||
m_Icon: {fileID: 0}
|
m_Icon: {fileID: 0}
|
||||||
m_NavMeshLayer: 0
|
m_NavMeshLayer: 0
|
||||||
|
@ -89,14 +92,20 @@ MonoBehaviour:
|
||||||
m_Name:
|
m_Name:
|
||||||
m_EditorClassIdentifier:
|
m_EditorClassIdentifier:
|
||||||
netProvider:
|
netProvider:
|
||||||
rid: 5474080437462106112
|
rid: 5474080454516408329
|
||||||
|
netClient:
|
||||||
|
rid: 5474080454516408330
|
||||||
|
steamService:
|
||||||
|
rid: 5474080454516408333
|
||||||
references:
|
references:
|
||||||
version: 2
|
version: 2
|
||||||
RefIds:
|
RefIds:
|
||||||
- rid: 5474080437462106112
|
- rid: 5474080454516408329
|
||||||
type: {class: NetProviderProxy, ns: BITKit, asm: BITKit}
|
type: {class: GDNetServiceSingleton, ns: BITKit, asm: BITKit.Extension.GameDesigner}
|
||||||
data:
|
- rid: 5474080454516408330
|
||||||
monoBehaviour: {fileID: -3428271289843395767}
|
type: {class: GDNetServiceSingleton, ns: BITKit, asm: BITKit.Extension.GameDesigner}
|
||||||
|
- rid: 5474080454516408333
|
||||||
|
type: {class: SteamServiceSingleton, ns: BITKit.Steamwork, asm: BITKit.Extension.Steamwork}
|
||||||
--- !u!114 &-2281902509228225294
|
--- !u!114 &-2281902509228225294
|
||||||
MonoBehaviour:
|
MonoBehaviour:
|
||||||
m_ObjectHideFlags: 0
|
m_ObjectHideFlags: 0
|
||||||
|
@ -126,12 +135,21 @@ MonoBehaviour:
|
||||||
serializedVersion: 2
|
serializedVersion: 2
|
||||||
m_Bits: 513
|
m_Bits: 513
|
||||||
defaultMaterial: {fileID: 11400000, guid: 6ce8f51b55ed1b84db162e849100dc10, type: 2}
|
defaultMaterial: {fileID: 11400000, guid: 6ce8f51b55ed1b84db162e849100dc10, type: 2}
|
||||||
|
netProvider:
|
||||||
|
rid: 5474080454516408321
|
||||||
pool:
|
pool:
|
||||||
prefab: {fileID: 2956281190107464547, guid: cd8502ee01a85944bbccb38128facc13,
|
prefab: {fileID: 2956281190107464547, guid: cd8502ee01a85944bbccb38128facc13,
|
||||||
type: 3}
|
type: 3}
|
||||||
root: {fileID: 1621845164855518716}
|
root: {fileID: 1621845164855518716}
|
||||||
instances: []
|
instances: []
|
||||||
--- !u!114 &-3428271289843395767
|
references:
|
||||||
|
version: 2
|
||||||
|
RefIds:
|
||||||
|
- rid: 5474080454516408321
|
||||||
|
type: {class: NetProviderProxy, ns: BITKit, asm: BITKit}
|
||||||
|
data:
|
||||||
|
monoBehaviour: {fileID: 2356180584613640822}
|
||||||
|
--- !u!114 &2356180584613640822
|
||||||
MonoBehaviour:
|
MonoBehaviour:
|
||||||
m_ObjectHideFlags: 0
|
m_ObjectHideFlags: 0
|
||||||
m_CorrespondingSourceObject: {fileID: 0}
|
m_CorrespondingSourceObject: {fileID: 0}
|
||||||
|
@ -143,17 +161,58 @@ MonoBehaviour:
|
||||||
m_Script: {fileID: 11500000, guid: 221e26c9881bfb840bc82c3587308e3e, type: 3}
|
m_Script: {fileID: 11500000, guid: 221e26c9881bfb840bc82c3587308e3e, type: 3}
|
||||||
m_Name:
|
m_Name:
|
||||||
m_EditorClassIdentifier:
|
m_EditorClassIdentifier:
|
||||||
address:
|
address: localhost
|
||||||
port: 0
|
port: 27014
|
||||||
clientProvider:
|
clientProvider:
|
||||||
rid: 5474080437462106113
|
rid: 5474080454516408320
|
||||||
references:
|
references:
|
||||||
version: 2
|
version: 2
|
||||||
RefIds:
|
RefIds:
|
||||||
- rid: 5474080437462106113
|
- rid: 5474080454516408320
|
||||||
type: {class: FlibClientProvider, ns: BITFALL, asm: BITFALL}
|
type: {class: GDNetClientProvider, ns: BITKit, asm: Assembly-CSharp-firstpass}
|
||||||
data:
|
data:
|
||||||
clientManager: {fileID: 4861076022157066155}
|
clientManager: {fileID: 4861076022157066155}
|
||||||
|
--- !u!114 &-3918555459250571244
|
||||||
|
MonoBehaviour:
|
||||||
|
m_ObjectHideFlags: 0
|
||||||
|
m_CorrespondingSourceObject: {fileID: 0}
|
||||||
|
m_PrefabInstance: {fileID: 0}
|
||||||
|
m_PrefabAsset: {fileID: 0}
|
||||||
|
m_GameObject: {fileID: 594564951014165300}
|
||||||
|
m_Enabled: 1
|
||||||
|
m_EditorHideFlags: 0
|
||||||
|
m_Script: {fileID: 11500000, guid: c754132856288ea4180e46d87fc46be9, type: 3}
|
||||||
|
m_Name:
|
||||||
|
m_EditorClassIdentifier:
|
||||||
|
vfxs:
|
||||||
|
- {fileID: 11400000, guid: ce6c3c9ba0efabc4ea63cfbcfc322a81, type: 2}
|
||||||
|
- {fileID: 11400000, guid: 02442f5995195f54b8bfc5883a53cf97, type: 2}
|
||||||
|
--- !u!114 &-31602009599847191
|
||||||
|
MonoBehaviour:
|
||||||
|
m_ObjectHideFlags: 0
|
||||||
|
m_CorrespondingSourceObject: {fileID: 0}
|
||||||
|
m_PrefabInstance: {fileID: 0}
|
||||||
|
m_PrefabAsset: {fileID: 0}
|
||||||
|
m_GameObject: {fileID: 594564951014165300}
|
||||||
|
m_Enabled: 1
|
||||||
|
m_EditorHideFlags: 0
|
||||||
|
m_Script: {fileID: 11500000, guid: 52fa20c3ba3f2664b9eb666a434b77de, type: 3}
|
||||||
|
m_Name:
|
||||||
|
m_EditorClassIdentifier:
|
||||||
|
prefab: {fileID: 5264291518813283261, guid: f18510934c4581d47819abfbf1bd3647, type: 3}
|
||||||
|
--- !u!114 &1510713985089303888
|
||||||
|
MonoBehaviour:
|
||||||
|
m_ObjectHideFlags: 0
|
||||||
|
m_CorrespondingSourceObject: {fileID: 0}
|
||||||
|
m_PrefabInstance: {fileID: 0}
|
||||||
|
m_PrefabAsset: {fileID: 0}
|
||||||
|
m_GameObject: {fileID: 594564951014165300}
|
||||||
|
m_Enabled: 1
|
||||||
|
m_EditorHideFlags: 0
|
||||||
|
m_Script: {fileID: 11500000, guid: 41cd0b8fd16c600468c5a24f0a273777, type: 3}
|
||||||
|
m_Name:
|
||||||
|
m_EditorClassIdentifier:
|
||||||
|
appId: 1934920
|
||||||
--- !u!1 &3982569034385566475
|
--- !u!1 &3982569034385566475
|
||||||
GameObject:
|
GameObject:
|
||||||
m_ObjectHideFlags: 0
|
m_ObjectHideFlags: 0
|
|
@ -1,47 +0,0 @@
|
||||||
%YAML 1.1
|
|
||||||
%TAG !u! tag:unity3d.com,2011:
|
|
||||||
--- !u!1 &8252820290161347513
|
|
||||||
GameObject:
|
|
||||||
m_ObjectHideFlags: 0
|
|
||||||
m_CorrespondingSourceObject: {fileID: 0}
|
|
||||||
m_PrefabInstance: {fileID: 0}
|
|
||||||
m_PrefabAsset: {fileID: 0}
|
|
||||||
serializedVersion: 6
|
|
||||||
m_Component:
|
|
||||||
- component: {fileID: 2812012559937706607}
|
|
||||||
- component: {fileID: 436460019296838824}
|
|
||||||
m_Layer: 0
|
|
||||||
m_Name: NetEntitesManager
|
|
||||||
m_TagString: Untagged
|
|
||||||
m_Icon: {fileID: 0}
|
|
||||||
m_NavMeshLayer: 0
|
|
||||||
m_StaticEditorFlags: 0
|
|
||||||
m_IsActive: 1
|
|
||||||
--- !u!4 &2812012559937706607
|
|
||||||
Transform:
|
|
||||||
m_ObjectHideFlags: 0
|
|
||||||
m_CorrespondingSourceObject: {fileID: 0}
|
|
||||||
m_PrefabInstance: {fileID: 0}
|
|
||||||
m_PrefabAsset: {fileID: 0}
|
|
||||||
m_GameObject: {fileID: 8252820290161347513}
|
|
||||||
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: []
|
|
||||||
m_Father: {fileID: 0}
|
|
||||||
m_RootOrder: 0
|
|
||||||
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
|
|
||||||
--- !u!114 &436460019296838824
|
|
||||||
MonoBehaviour:
|
|
||||||
m_ObjectHideFlags: 0
|
|
||||||
m_CorrespondingSourceObject: {fileID: 0}
|
|
||||||
m_PrefabInstance: {fileID: 0}
|
|
||||||
m_PrefabAsset: {fileID: 0}
|
|
||||||
m_GameObject: {fileID: 8252820290161347513}
|
|
||||||
m_Enabled: 1
|
|
||||||
m_EditorHideFlags: 0
|
|
||||||
m_Script: {fileID: 11500000, guid: 5702c065f2169b44a9c38206d85b23a2, type: 3}
|
|
||||||
m_Name:
|
|
||||||
m_EditorClassIdentifier:
|
|
||||||
proxy: {fileID: 5264291518813283261, guid: f18510934c4581d47819abfbf1bd3647, type: 3}
|
|
|
@ -1,46 +0,0 @@
|
||||||
%YAML 1.1
|
|
||||||
%TAG !u! tag:unity3d.com,2011:
|
|
||||||
--- !u!1 &1991127922467399889
|
|
||||||
GameObject:
|
|
||||||
m_ObjectHideFlags: 0
|
|
||||||
m_CorrespondingSourceObject: {fileID: 0}
|
|
||||||
m_PrefabInstance: {fileID: 0}
|
|
||||||
m_PrefabAsset: {fileID: 0}
|
|
||||||
serializedVersion: 6
|
|
||||||
m_Component:
|
|
||||||
- component: {fileID: 6775606062948898590}
|
|
||||||
- component: {fileID: 6663671466603395034}
|
|
||||||
m_Layer: 0
|
|
||||||
m_Name: PlayerService
|
|
||||||
m_TagString: Untagged
|
|
||||||
m_Icon: {fileID: 0}
|
|
||||||
m_NavMeshLayer: 0
|
|
||||||
m_StaticEditorFlags: 0
|
|
||||||
m_IsActive: 1
|
|
||||||
--- !u!4 &6775606062948898590
|
|
||||||
Transform:
|
|
||||||
m_ObjectHideFlags: 0
|
|
||||||
m_CorrespondingSourceObject: {fileID: 0}
|
|
||||||
m_PrefabInstance: {fileID: 0}
|
|
||||||
m_PrefabAsset: {fileID: 0}
|
|
||||||
m_GameObject: {fileID: 1991127922467399889}
|
|
||||||
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: []
|
|
||||||
m_Father: {fileID: 0}
|
|
||||||
m_RootOrder: 0
|
|
||||||
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
|
|
||||||
--- !u!114 &6663671466603395034
|
|
||||||
MonoBehaviour:
|
|
||||||
m_ObjectHideFlags: 0
|
|
||||||
m_CorrespondingSourceObject: {fileID: 0}
|
|
||||||
m_PrefabInstance: {fileID: 0}
|
|
||||||
m_PrefabAsset: {fileID: 0}
|
|
||||||
m_GameObject: {fileID: 1991127922467399889}
|
|
||||||
m_Enabled: 1
|
|
||||||
m_EditorHideFlags: 0
|
|
||||||
m_Script: {fileID: 11500000, guid: 33fef1205fe84a84f82d9526c5b68af4, type: 3}
|
|
||||||
m_Name:
|
|
||||||
m_EditorClassIdentifier:
|
|
|
@ -1,49 +0,0 @@
|
||||||
%YAML 1.1
|
|
||||||
%TAG !u! tag:unity3d.com,2011:
|
|
||||||
--- !u!1 &5736021920723147558
|
|
||||||
GameObject:
|
|
||||||
m_ObjectHideFlags: 0
|
|
||||||
m_CorrespondingSourceObject: {fileID: 0}
|
|
||||||
m_PrefabInstance: {fileID: 0}
|
|
||||||
m_PrefabAsset: {fileID: 0}
|
|
||||||
serializedVersion: 6
|
|
||||||
m_Component:
|
|
||||||
- component: {fileID: 5204725430344918013}
|
|
||||||
- component: {fileID: 7038145435044639555}
|
|
||||||
m_Layer: 0
|
|
||||||
m_Name: VFXManager
|
|
||||||
m_TagString: Untagged
|
|
||||||
m_Icon: {fileID: 2800000, guid: 0591aad39cd6a4245addb81f6332d852, type: 3}
|
|
||||||
m_NavMeshLayer: 0
|
|
||||||
m_StaticEditorFlags: 0
|
|
||||||
m_IsActive: 1
|
|
||||||
--- !u!4 &5204725430344918013
|
|
||||||
Transform:
|
|
||||||
m_ObjectHideFlags: 0
|
|
||||||
m_CorrespondingSourceObject: {fileID: 0}
|
|
||||||
m_PrefabInstance: {fileID: 0}
|
|
||||||
m_PrefabAsset: {fileID: 0}
|
|
||||||
m_GameObject: {fileID: 5736021920723147558}
|
|
||||||
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: []
|
|
||||||
m_Father: {fileID: 0}
|
|
||||||
m_RootOrder: 0
|
|
||||||
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
|
|
||||||
--- !u!114 &7038145435044639555
|
|
||||||
MonoBehaviour:
|
|
||||||
m_ObjectHideFlags: 0
|
|
||||||
m_CorrespondingSourceObject: {fileID: 0}
|
|
||||||
m_PrefabInstance: {fileID: 0}
|
|
||||||
m_PrefabAsset: {fileID: 0}
|
|
||||||
m_GameObject: {fileID: 5736021920723147558}
|
|
||||||
m_Enabled: 1
|
|
||||||
m_EditorHideFlags: 0
|
|
||||||
m_Script: {fileID: 11500000, guid: c754132856288ea4180e46d87fc46be9, type: 3}
|
|
||||||
m_Name:
|
|
||||||
m_EditorClassIdentifier:
|
|
||||||
vfxs:
|
|
||||||
- {fileID: 11400000, guid: ce6c3c9ba0efabc4ea63cfbcfc322a81, type: 2}
|
|
||||||
- {fileID: 11400000, guid: 02442f5995195f54b8bfc5883a53cf97, type: 2}
|
|
|
@ -407,7 +407,7 @@ Transform:
|
||||||
m_ConstrainProportionsScale: 0
|
m_ConstrainProportionsScale: 0
|
||||||
m_Children: []
|
m_Children: []
|
||||||
m_Father: {fileID: 0}
|
m_Father: {fileID: 0}
|
||||||
m_RootOrder: 12
|
m_RootOrder: 11
|
||||||
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
|
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
|
||||||
--- !u!1001 &109367991
|
--- !u!1001 &109367991
|
||||||
PrefabInstance:
|
PrefabInstance:
|
||||||
|
@ -884,7 +884,7 @@ PrefabInstance:
|
||||||
- target: {fileID: 4305911198204250499, guid: 08bf595b66a0f9347973cbccd7039436,
|
- target: {fileID: 4305911198204250499, guid: 08bf595b66a0f9347973cbccd7039436,
|
||||||
type: 3}
|
type: 3}
|
||||||
propertyPath: m_RootOrder
|
propertyPath: m_RootOrder
|
||||||
value: 24
|
value: 23
|
||||||
objectReference: {fileID: 0}
|
objectReference: {fileID: 0}
|
||||||
- target: {fileID: 4305911198204250499, guid: 08bf595b66a0f9347973cbccd7039436,
|
- target: {fileID: 4305911198204250499, guid: 08bf595b66a0f9347973cbccd7039436,
|
||||||
type: 3}
|
type: 3}
|
||||||
|
@ -2053,7 +2053,7 @@ PrefabInstance:
|
||||||
- target: {fileID: 4305911198204250499, guid: 08bf595b66a0f9347973cbccd7039436,
|
- target: {fileID: 4305911198204250499, guid: 08bf595b66a0f9347973cbccd7039436,
|
||||||
type: 3}
|
type: 3}
|
||||||
propertyPath: m_RootOrder
|
propertyPath: m_RootOrder
|
||||||
value: 21
|
value: 20
|
||||||
objectReference: {fileID: 0}
|
objectReference: {fileID: 0}
|
||||||
- target: {fileID: 4305911198204250499, guid: 08bf595b66a0f9347973cbccd7039436,
|
- target: {fileID: 4305911198204250499, guid: 08bf595b66a0f9347973cbccd7039436,
|
||||||
type: 3}
|
type: 3}
|
||||||
|
@ -2366,7 +2366,7 @@ Transform:
|
||||||
m_ConstrainProportionsScale: 0
|
m_ConstrainProportionsScale: 0
|
||||||
m_Children: []
|
m_Children: []
|
||||||
m_Father: {fileID: 0}
|
m_Father: {fileID: 0}
|
||||||
m_RootOrder: 19
|
m_RootOrder: 18
|
||||||
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
|
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
|
||||||
--- !u!1 &522866409
|
--- !u!1 &522866409
|
||||||
GameObject:
|
GameObject:
|
||||||
|
@ -3105,7 +3105,7 @@ Transform:
|
||||||
m_Children:
|
m_Children:
|
||||||
- {fileID: 282301062}
|
- {fileID: 282301062}
|
||||||
m_Father: {fileID: 0}
|
m_Father: {fileID: 0}
|
||||||
m_RootOrder: 4
|
m_RootOrder: 3
|
||||||
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
|
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
|
||||||
--- !u!1 &595285511
|
--- !u!1 &595285511
|
||||||
GameObject:
|
GameObject:
|
||||||
|
@ -4001,7 +4001,7 @@ Transform:
|
||||||
m_Children:
|
m_Children:
|
||||||
- {fileID: 522866411}
|
- {fileID: 522866411}
|
||||||
m_Father: {fileID: 0}
|
m_Father: {fileID: 0}
|
||||||
m_RootOrder: 29
|
m_RootOrder: 28
|
||||||
m_LocalEulerAnglesHint: {x: 0, y: -180, z: 0}
|
m_LocalEulerAnglesHint: {x: 0, y: -180, z: 0}
|
||||||
--- !u!114 &835177943
|
--- !u!114 &835177943
|
||||||
MonoBehaviour:
|
MonoBehaviour:
|
||||||
|
@ -4410,7 +4410,7 @@ Transform:
|
||||||
m_ConstrainProportionsScale: 0
|
m_ConstrainProportionsScale: 0
|
||||||
m_Children: []
|
m_Children: []
|
||||||
m_Father: {fileID: 0}
|
m_Father: {fileID: 0}
|
||||||
m_RootOrder: 3
|
m_RootOrder: 2
|
||||||
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
|
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
|
||||||
--- !u!114 &963194229
|
--- !u!114 &963194229
|
||||||
MonoBehaviour:
|
MonoBehaviour:
|
||||||
|
@ -4681,7 +4681,7 @@ Transform:
|
||||||
m_ConstrainProportionsScale: 0
|
m_ConstrainProportionsScale: 0
|
||||||
m_Children: []
|
m_Children: []
|
||||||
m_Father: {fileID: 0}
|
m_Father: {fileID: 0}
|
||||||
m_RootOrder: 2
|
m_RootOrder: 1
|
||||||
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
|
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
|
||||||
--- !u!114 &988449214
|
--- !u!114 &988449214
|
||||||
MonoBehaviour:
|
MonoBehaviour:
|
||||||
|
@ -5722,7 +5722,7 @@ Transform:
|
||||||
m_ConstrainProportionsScale: 0
|
m_ConstrainProportionsScale: 0
|
||||||
m_Children: []
|
m_Children: []
|
||||||
m_Father: {fileID: 0}
|
m_Father: {fileID: 0}
|
||||||
m_RootOrder: 7
|
m_RootOrder: 6
|
||||||
m_LocalEulerAnglesHint: {x: 34.397, y: -170.858, z: 13.288}
|
m_LocalEulerAnglesHint: {x: 34.397, y: -170.858, z: 13.288}
|
||||||
--- !u!114 &1051082604
|
--- !u!114 &1051082604
|
||||||
MonoBehaviour:
|
MonoBehaviour:
|
||||||
|
@ -5833,7 +5833,7 @@ Transform:
|
||||||
- {fileID: 1886431281}
|
- {fileID: 1886431281}
|
||||||
- {fileID: 1049391285}
|
- {fileID: 1049391285}
|
||||||
m_Father: {fileID: 0}
|
m_Father: {fileID: 0}
|
||||||
m_RootOrder: 9
|
m_RootOrder: 8
|
||||||
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
|
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
|
||||||
--- !u!1 &1076798597
|
--- !u!1 &1076798597
|
||||||
GameObject:
|
GameObject:
|
||||||
|
@ -5908,7 +5908,7 @@ Transform:
|
||||||
m_ConstrainProportionsScale: 0
|
m_ConstrainProportionsScale: 0
|
||||||
m_Children: []
|
m_Children: []
|
||||||
m_Father: {fileID: 0}
|
m_Father: {fileID: 0}
|
||||||
m_RootOrder: 8
|
m_RootOrder: 7
|
||||||
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
|
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
|
||||||
--- !u!1 &1088581380
|
--- !u!1 &1088581380
|
||||||
GameObject:
|
GameObject:
|
||||||
|
@ -6487,7 +6487,7 @@ PrefabInstance:
|
||||||
- target: {fileID: 4305911198204250499, guid: 08bf595b66a0f9347973cbccd7039436,
|
- target: {fileID: 4305911198204250499, guid: 08bf595b66a0f9347973cbccd7039436,
|
||||||
type: 3}
|
type: 3}
|
||||||
propertyPath: m_RootOrder
|
propertyPath: m_RootOrder
|
||||||
value: 22
|
value: 21
|
||||||
objectReference: {fileID: 0}
|
objectReference: {fileID: 0}
|
||||||
- target: {fileID: 4305911198204250499, guid: 08bf595b66a0f9347973cbccd7039436,
|
- target: {fileID: 4305911198204250499, guid: 08bf595b66a0f9347973cbccd7039436,
|
||||||
type: 3}
|
type: 3}
|
||||||
|
@ -6860,6 +6860,8 @@ MonoBehaviour:
|
||||||
cursor: 1
|
cursor: 1
|
||||||
allowInput: 0
|
allowInput: 0
|
||||||
isAdditive: 0
|
isAdditive: 0
|
||||||
|
netClient:
|
||||||
|
rid: 5474080454516408323
|
||||||
connectButton: {fileID: 1482044486}
|
connectButton: {fileID: 1482044486}
|
||||||
localhostButton: {fileID: 1489141484}
|
localhostButton: {fileID: 1489141484}
|
||||||
disconnectButton: {fileID: 59175076}
|
disconnectButton: {fileID: 59175076}
|
||||||
|
@ -6870,6 +6872,11 @@ MonoBehaviour:
|
||||||
inputActionGroup:
|
inputActionGroup:
|
||||||
allowGlobalActivation: 0
|
allowGlobalActivation: 0
|
||||||
isEnabled: 0
|
isEnabled: 0
|
||||||
|
references:
|
||||||
|
version: 2
|
||||||
|
RefIds:
|
||||||
|
- rid: 5474080454516408323
|
||||||
|
type: {class: GDNetServiceSingleton, ns: BITKit, asm: BITKit.Extension.GameDesigner}
|
||||||
--- !u!114 &1229624391
|
--- !u!114 &1229624391
|
||||||
MonoBehaviour:
|
MonoBehaviour:
|
||||||
m_ObjectHideFlags: 0
|
m_ObjectHideFlags: 0
|
||||||
|
@ -7468,8 +7475,19 @@ MonoBehaviour:
|
||||||
cursor: 1
|
cursor: 1
|
||||||
allowInput: 0
|
allowInput: 0
|
||||||
isAdditive: 0
|
isAdditive: 0
|
||||||
|
netClient:
|
||||||
|
rid: 5474080454516408327
|
||||||
|
netProvider:
|
||||||
|
rid: 5474080454516408328
|
||||||
loadBar: {fileID: 794431912}
|
loadBar: {fileID: 794431912}
|
||||||
loadText: {fileID: 1950290476}
|
loadText: {fileID: 1950290476}
|
||||||
|
references:
|
||||||
|
version: 2
|
||||||
|
RefIds:
|
||||||
|
- rid: 5474080454516408327
|
||||||
|
type: {class: GDNetServiceSingleton, ns: BITKit, asm: BITKit.Extension.GameDesigner}
|
||||||
|
- rid: 5474080454516408328
|
||||||
|
type: {class: GDNetServiceSingleton, ns: BITKit, asm: BITKit.Extension.GameDesigner}
|
||||||
--- !u!114 &1316390899
|
--- !u!114 &1316390899
|
||||||
MonoBehaviour:
|
MonoBehaviour:
|
||||||
m_ObjectHideFlags: 0
|
m_ObjectHideFlags: 0
|
||||||
|
@ -8176,7 +8194,7 @@ Transform:
|
||||||
- {fileID: 1229624388}
|
- {fileID: 1229624388}
|
||||||
- {fileID: 1316390897}
|
- {fileID: 1316390897}
|
||||||
m_Father: {fileID: 0}
|
m_Father: {fileID: 0}
|
||||||
m_RootOrder: 6
|
m_RootOrder: 5
|
||||||
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
|
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
|
||||||
--- !u!1001 &1514697182
|
--- !u!1001 &1514697182
|
||||||
PrefabInstance:
|
PrefabInstance:
|
||||||
|
@ -8398,7 +8416,7 @@ PrefabInstance:
|
||||||
- target: {fileID: 4305911198204250499, guid: 08bf595b66a0f9347973cbccd7039436,
|
- target: {fileID: 4305911198204250499, guid: 08bf595b66a0f9347973cbccd7039436,
|
||||||
type: 3}
|
type: 3}
|
||||||
propertyPath: m_RootOrder
|
propertyPath: m_RootOrder
|
||||||
value: 23
|
value: 22
|
||||||
objectReference: {fileID: 0}
|
objectReference: {fileID: 0}
|
||||||
- target: {fileID: 4305911198204250499, guid: 08bf595b66a0f9347973cbccd7039436,
|
- target: {fileID: 4305911198204250499, guid: 08bf595b66a0f9347973cbccd7039436,
|
||||||
type: 3}
|
type: 3}
|
||||||
|
@ -8557,7 +8575,7 @@ PrefabInstance:
|
||||||
- target: {fileID: 2925653066038063199, guid: c7d364eea8941e847b69eba0d43e22b6,
|
- target: {fileID: 2925653066038063199, guid: c7d364eea8941e847b69eba0d43e22b6,
|
||||||
type: 3}
|
type: 3}
|
||||||
propertyPath: m_RootOrder
|
propertyPath: m_RootOrder
|
||||||
value: 31
|
value: 29
|
||||||
objectReference: {fileID: 0}
|
objectReference: {fileID: 0}
|
||||||
- target: {fileID: 2925653066038063199, guid: c7d364eea8941e847b69eba0d43e22b6,
|
- target: {fileID: 2925653066038063199, guid: c7d364eea8941e847b69eba0d43e22b6,
|
||||||
type: 3}
|
type: 3}
|
||||||
|
@ -9007,7 +9025,7 @@ Transform:
|
||||||
- {fileID: 567279688}
|
- {fileID: 567279688}
|
||||||
- {fileID: 1854426442}
|
- {fileID: 1854426442}
|
||||||
m_Father: {fileID: 0}
|
m_Father: {fileID: 0}
|
||||||
m_RootOrder: 10
|
m_RootOrder: 9
|
||||||
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
|
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
|
||||||
--- !u!1001 &1677499543
|
--- !u!1001 &1677499543
|
||||||
PrefabInstance:
|
PrefabInstance:
|
||||||
|
@ -9024,7 +9042,7 @@ PrefabInstance:
|
||||||
- target: {fileID: 2925653066038063199, guid: c7d364eea8941e847b69eba0d43e22b6,
|
- target: {fileID: 2925653066038063199, guid: c7d364eea8941e847b69eba0d43e22b6,
|
||||||
type: 3}
|
type: 3}
|
||||||
propertyPath: m_RootOrder
|
propertyPath: m_RootOrder
|
||||||
value: 32
|
value: 30
|
||||||
objectReference: {fileID: 0}
|
objectReference: {fileID: 0}
|
||||||
- target: {fileID: 2925653066038063199, guid: c7d364eea8941e847b69eba0d43e22b6,
|
- target: {fileID: 2925653066038063199, guid: c7d364eea8941e847b69eba0d43e22b6,
|
||||||
type: 3}
|
type: 3}
|
||||||
|
@ -9424,7 +9442,7 @@ Transform:
|
||||||
m_ConstrainProportionsScale: 0
|
m_ConstrainProportionsScale: 0
|
||||||
m_Children: []
|
m_Children: []
|
||||||
m_Father: {fileID: 0}
|
m_Father: {fileID: 0}
|
||||||
m_RootOrder: 11
|
m_RootOrder: 10
|
||||||
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
|
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
|
||||||
--- !u!1001 &1720213259
|
--- !u!1001 &1720213259
|
||||||
PrefabInstance:
|
PrefabInstance:
|
||||||
|
@ -9531,7 +9549,7 @@ Transform:
|
||||||
m_Children:
|
m_Children:
|
||||||
- {fileID: 1076798598}
|
- {fileID: 1076798598}
|
||||||
m_Father: {fileID: 0}
|
m_Father: {fileID: 0}
|
||||||
m_RootOrder: 16
|
m_RootOrder: 15
|
||||||
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
|
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
|
||||||
--- !u!1001 &1762130623
|
--- !u!1001 &1762130623
|
||||||
PrefabInstance:
|
PrefabInstance:
|
||||||
|
@ -11174,7 +11192,7 @@ Transform:
|
||||||
m_ConstrainProportionsScale: 0
|
m_ConstrainProportionsScale: 0
|
||||||
m_Children: []
|
m_Children: []
|
||||||
m_Father: {fileID: 0}
|
m_Father: {fileID: 0}
|
||||||
m_RootOrder: 5
|
m_RootOrder: 4
|
||||||
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
|
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
|
||||||
--- !u!1001 &1948782258
|
--- !u!1001 &1948782258
|
||||||
PrefabInstance:
|
PrefabInstance:
|
||||||
|
@ -11935,6 +11953,10 @@ MonoBehaviour:
|
||||||
cursor: 0
|
cursor: 0
|
||||||
allowInput: 1
|
allowInput: 1
|
||||||
isAdditive: 0
|
isAdditive: 0
|
||||||
|
netClient:
|
||||||
|
rid: 5474080454516408324
|
||||||
|
netProvider:
|
||||||
|
rid: 5474080454516408326
|
||||||
inventoryAction: {fileID: 4731022410478041803, guid: e0e9267cab824e8489fc27d83f1d07b7,
|
inventoryAction: {fileID: 4731022410478041803, guid: e0e9267cab824e8489fc27d83f1d07b7,
|
||||||
type: 3}
|
type: 3}
|
||||||
returnAction: {fileID: 7656137919724235468, guid: e0e9267cab824e8489fc27d83f1d07b7,
|
returnAction: {fileID: 7656137919724235468, guid: e0e9267cab824e8489fc27d83f1d07b7,
|
||||||
|
@ -11943,6 +11965,13 @@ MonoBehaviour:
|
||||||
allowGlobalActivation: 0
|
allowGlobalActivation: 0
|
||||||
isEnabled: 0
|
isEnabled: 0
|
||||||
nameLabel: {fileID: 440857355}
|
nameLabel: {fileID: 440857355}
|
||||||
|
references:
|
||||||
|
version: 2
|
||||||
|
RefIds:
|
||||||
|
- rid: 5474080454516408324
|
||||||
|
type: {class: GDNetServiceSingleton, ns: BITKit, asm: BITKit.Extension.GameDesigner}
|
||||||
|
- rid: 5474080454516408326
|
||||||
|
type: {class: GDNetServiceSingleton, ns: BITKit, asm: BITKit.Extension.GameDesigner}
|
||||||
--- !u!114 &2108612510
|
--- !u!114 &2108612510
|
||||||
MonoBehaviour:
|
MonoBehaviour:
|
||||||
m_ObjectHideFlags: 0
|
m_ObjectHideFlags: 0
|
||||||
|
@ -12167,144 +12196,6 @@ Transform:
|
||||||
type: 3}
|
type: 3}
|
||||||
m_PrefabInstance: {fileID: 2126687261}
|
m_PrefabInstance: {fileID: 2126687261}
|
||||||
m_PrefabAsset: {fileID: 0}
|
m_PrefabAsset: {fileID: 0}
|
||||||
--- !u!1001 &1222469988293950491
|
|
||||||
PrefabInstance:
|
|
||||||
m_ObjectHideFlags: 0
|
|
||||||
serializedVersion: 2
|
|
||||||
m_Modification:
|
|
||||||
m_TransformParent: {fileID: 0}
|
|
||||||
m_Modifications:
|
|
||||||
- target: {fileID: 2812012559937706607, guid: 9aabcf83d34f3794ab780926fe571c74,
|
|
||||||
type: 3}
|
|
||||||
propertyPath: m_RootOrder
|
|
||||||
value: 30
|
|
||||||
objectReference: {fileID: 0}
|
|
||||||
- target: {fileID: 2812012559937706607, guid: 9aabcf83d34f3794ab780926fe571c74,
|
|
||||||
type: 3}
|
|
||||||
propertyPath: m_LocalPosition.x
|
|
||||||
value: 0
|
|
||||||
objectReference: {fileID: 0}
|
|
||||||
- target: {fileID: 2812012559937706607, guid: 9aabcf83d34f3794ab780926fe571c74,
|
|
||||||
type: 3}
|
|
||||||
propertyPath: m_LocalPosition.y
|
|
||||||
value: 0
|
|
||||||
objectReference: {fileID: 0}
|
|
||||||
- target: {fileID: 2812012559937706607, guid: 9aabcf83d34f3794ab780926fe571c74,
|
|
||||||
type: 3}
|
|
||||||
propertyPath: m_LocalPosition.z
|
|
||||||
value: 0
|
|
||||||
objectReference: {fileID: 0}
|
|
||||||
- target: {fileID: 2812012559937706607, guid: 9aabcf83d34f3794ab780926fe571c74,
|
|
||||||
type: 3}
|
|
||||||
propertyPath: m_LocalRotation.w
|
|
||||||
value: 1
|
|
||||||
objectReference: {fileID: 0}
|
|
||||||
- target: {fileID: 2812012559937706607, guid: 9aabcf83d34f3794ab780926fe571c74,
|
|
||||||
type: 3}
|
|
||||||
propertyPath: m_LocalRotation.x
|
|
||||||
value: 0
|
|
||||||
objectReference: {fileID: 0}
|
|
||||||
- target: {fileID: 2812012559937706607, guid: 9aabcf83d34f3794ab780926fe571c74,
|
|
||||||
type: 3}
|
|
||||||
propertyPath: m_LocalRotation.y
|
|
||||||
value: 0
|
|
||||||
objectReference: {fileID: 0}
|
|
||||||
- target: {fileID: 2812012559937706607, guid: 9aabcf83d34f3794ab780926fe571c74,
|
|
||||||
type: 3}
|
|
||||||
propertyPath: m_LocalRotation.z
|
|
||||||
value: 0
|
|
||||||
objectReference: {fileID: 0}
|
|
||||||
- target: {fileID: 2812012559937706607, guid: 9aabcf83d34f3794ab780926fe571c74,
|
|
||||||
type: 3}
|
|
||||||
propertyPath: m_LocalEulerAnglesHint.x
|
|
||||||
value: 0
|
|
||||||
objectReference: {fileID: 0}
|
|
||||||
- target: {fileID: 2812012559937706607, guid: 9aabcf83d34f3794ab780926fe571c74,
|
|
||||||
type: 3}
|
|
||||||
propertyPath: m_LocalEulerAnglesHint.y
|
|
||||||
value: 0
|
|
||||||
objectReference: {fileID: 0}
|
|
||||||
- target: {fileID: 2812012559937706607, guid: 9aabcf83d34f3794ab780926fe571c74,
|
|
||||||
type: 3}
|
|
||||||
propertyPath: m_LocalEulerAnglesHint.z
|
|
||||||
value: 0
|
|
||||||
objectReference: {fileID: 0}
|
|
||||||
- target: {fileID: 8252820290161347513, guid: 9aabcf83d34f3794ab780926fe571c74,
|
|
||||||
type: 3}
|
|
||||||
propertyPath: m_Name
|
|
||||||
value: NetEntitesManager
|
|
||||||
objectReference: {fileID: 0}
|
|
||||||
m_RemovedComponents: []
|
|
||||||
m_SourcePrefab: {fileID: 100100000, guid: 9aabcf83d34f3794ab780926fe571c74, type: 3}
|
|
||||||
--- !u!1001 &1775590821995709921
|
|
||||||
PrefabInstance:
|
|
||||||
m_ObjectHideFlags: 0
|
|
||||||
serializedVersion: 2
|
|
||||||
m_Modification:
|
|
||||||
m_TransformParent: {fileID: 0}
|
|
||||||
m_Modifications:
|
|
||||||
- target: {fileID: 5204725430344918013, guid: a14f3b822df215843adc179710c090a3,
|
|
||||||
type: 3}
|
|
||||||
propertyPath: m_RootOrder
|
|
||||||
value: 1
|
|
||||||
objectReference: {fileID: 0}
|
|
||||||
- target: {fileID: 5204725430344918013, guid: a14f3b822df215843adc179710c090a3,
|
|
||||||
type: 3}
|
|
||||||
propertyPath: m_LocalPosition.x
|
|
||||||
value: 0
|
|
||||||
objectReference: {fileID: 0}
|
|
||||||
- target: {fileID: 5204725430344918013, guid: a14f3b822df215843adc179710c090a3,
|
|
||||||
type: 3}
|
|
||||||
propertyPath: m_LocalPosition.y
|
|
||||||
value: 0
|
|
||||||
objectReference: {fileID: 0}
|
|
||||||
- target: {fileID: 5204725430344918013, guid: a14f3b822df215843adc179710c090a3,
|
|
||||||
type: 3}
|
|
||||||
propertyPath: m_LocalPosition.z
|
|
||||||
value: 0
|
|
||||||
objectReference: {fileID: 0}
|
|
||||||
- target: {fileID: 5204725430344918013, guid: a14f3b822df215843adc179710c090a3,
|
|
||||||
type: 3}
|
|
||||||
propertyPath: m_LocalRotation.w
|
|
||||||
value: 1
|
|
||||||
objectReference: {fileID: 0}
|
|
||||||
- target: {fileID: 5204725430344918013, guid: a14f3b822df215843adc179710c090a3,
|
|
||||||
type: 3}
|
|
||||||
propertyPath: m_LocalRotation.x
|
|
||||||
value: 0
|
|
||||||
objectReference: {fileID: 0}
|
|
||||||
- target: {fileID: 5204725430344918013, guid: a14f3b822df215843adc179710c090a3,
|
|
||||||
type: 3}
|
|
||||||
propertyPath: m_LocalRotation.y
|
|
||||||
value: 0
|
|
||||||
objectReference: {fileID: 0}
|
|
||||||
- target: {fileID: 5204725430344918013, guid: a14f3b822df215843adc179710c090a3,
|
|
||||||
type: 3}
|
|
||||||
propertyPath: m_LocalRotation.z
|
|
||||||
value: 0
|
|
||||||
objectReference: {fileID: 0}
|
|
||||||
- target: {fileID: 5204725430344918013, guid: a14f3b822df215843adc179710c090a3,
|
|
||||||
type: 3}
|
|
||||||
propertyPath: m_LocalEulerAnglesHint.x
|
|
||||||
value: 0
|
|
||||||
objectReference: {fileID: 0}
|
|
||||||
- target: {fileID: 5204725430344918013, guid: a14f3b822df215843adc179710c090a3,
|
|
||||||
type: 3}
|
|
||||||
propertyPath: m_LocalEulerAnglesHint.y
|
|
||||||
value: 0
|
|
||||||
objectReference: {fileID: 0}
|
|
||||||
- target: {fileID: 5204725430344918013, guid: a14f3b822df215843adc179710c090a3,
|
|
||||||
type: 3}
|
|
||||||
propertyPath: m_LocalEulerAnglesHint.z
|
|
||||||
value: 0
|
|
||||||
objectReference: {fileID: 0}
|
|
||||||
- target: {fileID: 5736021920723147558, guid: a14f3b822df215843adc179710c090a3,
|
|
||||||
type: 3}
|
|
||||||
propertyPath: m_Name
|
|
||||||
value: VFXManager
|
|
||||||
objectReference: {fileID: 0}
|
|
||||||
m_RemovedComponents: []
|
|
||||||
m_SourcePrefab: {fileID: 100100000, guid: a14f3b822df215843adc179710c090a3, type: 3}
|
|
||||||
--- !u!1001 &2425374285907649514
|
--- !u!1001 &2425374285907649514
|
||||||
PrefabInstance:
|
PrefabInstance:
|
||||||
m_ObjectHideFlags: 0
|
m_ObjectHideFlags: 0
|
||||||
|
@ -12320,7 +12211,7 @@ PrefabInstance:
|
||||||
- target: {fileID: 1927291751145116269, guid: d35acde394701754dbb50a0f9421c492,
|
- target: {fileID: 1927291751145116269, guid: d35acde394701754dbb50a0f9421c492,
|
||||||
type: 3}
|
type: 3}
|
||||||
propertyPath: m_RootOrder
|
propertyPath: m_RootOrder
|
||||||
value: 26
|
value: 25
|
||||||
objectReference: {fileID: 0}
|
objectReference: {fileID: 0}
|
||||||
- target: {fileID: 1927291751145116269, guid: d35acde394701754dbb50a0f9421c492,
|
- target: {fileID: 1927291751145116269, guid: d35acde394701754dbb50a0f9421c492,
|
||||||
type: 3}
|
type: 3}
|
||||||
|
@ -12384,7 +12275,7 @@ PrefabInstance:
|
||||||
- target: {fileID: 5681355521161477298, guid: 91b80a7cf885c984ea8d0d306d167dea,
|
- target: {fileID: 5681355521161477298, guid: 91b80a7cf885c984ea8d0d306d167dea,
|
||||||
type: 3}
|
type: 3}
|
||||||
propertyPath: m_RootOrder
|
propertyPath: m_RootOrder
|
||||||
value: 25
|
value: 24
|
||||||
objectReference: {fileID: 0}
|
objectReference: {fileID: 0}
|
||||||
- target: {fileID: 5681355521161477298, guid: 91b80a7cf885c984ea8d0d306d167dea,
|
- target: {fileID: 5681355521161477298, guid: 91b80a7cf885c984ea8d0d306d167dea,
|
||||||
type: 3}
|
type: 3}
|
||||||
|
@ -12453,7 +12344,7 @@ PrefabInstance:
|
||||||
- target: {fileID: 2956281190107464546, guid: cd8502ee01a85944bbccb38128facc13,
|
- target: {fileID: 2956281190107464546, guid: cd8502ee01a85944bbccb38128facc13,
|
||||||
type: 3}
|
type: 3}
|
||||||
propertyPath: m_RootOrder
|
propertyPath: m_RootOrder
|
||||||
value: 17
|
value: 16
|
||||||
objectReference: {fileID: 0}
|
objectReference: {fileID: 0}
|
||||||
- target: {fileID: 2956281190107464546, guid: cd8502ee01a85944bbccb38128facc13,
|
- target: {fileID: 2956281190107464546, guid: cd8502ee01a85944bbccb38128facc13,
|
||||||
type: 3}
|
type: 3}
|
||||||
|
@ -12527,7 +12418,7 @@ PrefabInstance:
|
||||||
- target: {fileID: 4258070653194797575, guid: d8b5a76c92d6b3a4592b14e21ad018c0,
|
- target: {fileID: 4258070653194797575, guid: d8b5a76c92d6b3a4592b14e21ad018c0,
|
||||||
type: 3}
|
type: 3}
|
||||||
propertyPath: m_RootOrder
|
propertyPath: m_RootOrder
|
||||||
value: 18
|
value: 17
|
||||||
objectReference: {fileID: 0}
|
objectReference: {fileID: 0}
|
||||||
- target: {fileID: 4258070653194797575, guid: d8b5a76c92d6b3a4592b14e21ad018c0,
|
- target: {fileID: 4258070653194797575, guid: d8b5a76c92d6b3a4592b14e21ad018c0,
|
||||||
type: 3}
|
type: 3}
|
||||||
|
@ -12588,6 +12479,21 @@ PrefabInstance:
|
||||||
m_Modification:
|
m_Modification:
|
||||||
m_TransformParent: {fileID: 0}
|
m_TransformParent: {fileID: 0}
|
||||||
m_Modifications:
|
m_Modifications:
|
||||||
|
- target: {fileID: 2367504132869257504, guid: e5d265393747af741b4f5d719598831a,
|
||||||
|
type: 3}
|
||||||
|
propertyPath: m_LocalRotation.w
|
||||||
|
value: -0.00000019861227
|
||||||
|
objectReference: {fileID: 0}
|
||||||
|
- target: {fileID: 3956412582329371354, guid: e5d265393747af741b4f5d719598831a,
|
||||||
|
type: 3}
|
||||||
|
propertyPath: m_LocalPosition.x
|
||||||
|
value: -0.00000011920929
|
||||||
|
objectReference: {fileID: 0}
|
||||||
|
- target: {fileID: 3956412582329371354, guid: e5d265393747af741b4f5d719598831a,
|
||||||
|
type: 3}
|
||||||
|
propertyPath: m_LocalPosition.z
|
||||||
|
value: -0.00000020647656
|
||||||
|
objectReference: {fileID: 0}
|
||||||
- target: {fileID: 4826102346843731729, guid: e5d265393747af741b4f5d719598831a,
|
- target: {fileID: 4826102346843731729, guid: e5d265393747af741b4f5d719598831a,
|
||||||
type: 3}
|
type: 3}
|
||||||
propertyPath: m_Name
|
propertyPath: m_Name
|
||||||
|
@ -12601,7 +12507,7 @@ PrefabInstance:
|
||||||
- target: {fileID: 4826102346843731735, guid: e5d265393747af741b4f5d719598831a,
|
- target: {fileID: 4826102346843731735, guid: e5d265393747af741b4f5d719598831a,
|
||||||
type: 3}
|
type: 3}
|
||||||
propertyPath: m_RootOrder
|
propertyPath: m_RootOrder
|
||||||
value: 14
|
value: 13
|
||||||
objectReference: {fileID: 0}
|
objectReference: {fileID: 0}
|
||||||
- target: {fileID: 4826102346843731735, guid: e5d265393747af741b4f5d719598831a,
|
- target: {fileID: 4826102346843731735, guid: e5d265393747af741b4f5d719598831a,
|
||||||
type: 3}
|
type: 3}
|
||||||
|
@ -12653,6 +12559,11 @@ PrefabInstance:
|
||||||
propertyPath: m_LocalEulerAnglesHint.z
|
propertyPath: m_LocalEulerAnglesHint.z
|
||||||
value: 0
|
value: 0
|
||||||
objectReference: {fileID: 0}
|
objectReference: {fileID: 0}
|
||||||
|
- target: {fileID: 6543478755785382772, guid: e5d265393747af741b4f5d719598831a,
|
||||||
|
type: 3}
|
||||||
|
propertyPath: m_RotationOffsets.Array.data[0].x
|
||||||
|
value: -89.97203
|
||||||
|
objectReference: {fileID: 0}
|
||||||
m_RemovedComponents: []
|
m_RemovedComponents: []
|
||||||
m_SourcePrefab: {fileID: 100100000, guid: e5d265393747af741b4f5d719598831a, type: 3}
|
m_SourcePrefab: {fileID: 100100000, guid: e5d265393747af741b4f5d719598831a, type: 3}
|
||||||
--- !u!1001 &4967360553653707449
|
--- !u!1001 &4967360553653707449
|
||||||
|
@ -12665,7 +12576,7 @@ PrefabInstance:
|
||||||
- target: {fileID: 4967360553763134876, guid: afc3896ae91cb60479e82dc81a530310,
|
- target: {fileID: 4967360553763134876, guid: afc3896ae91cb60479e82dc81a530310,
|
||||||
type: 3}
|
type: 3}
|
||||||
propertyPath: m_RootOrder
|
propertyPath: m_RootOrder
|
||||||
value: 13
|
value: 12
|
||||||
objectReference: {fileID: 0}
|
objectReference: {fileID: 0}
|
||||||
- target: {fileID: 4967360553763134876, guid: afc3896ae91cb60479e82dc81a530310,
|
- target: {fileID: 4967360553763134876, guid: afc3896ae91cb60479e82dc81a530310,
|
||||||
type: 3}
|
type: 3}
|
||||||
|
@ -12899,7 +12810,7 @@ PrefabInstance:
|
||||||
- target: {fileID: 5088247503209915273, guid: f18510934c4581d47819abfbf1bd3647,
|
- target: {fileID: 5088247503209915273, guid: f18510934c4581d47819abfbf1bd3647,
|
||||||
type: 3}
|
type: 3}
|
||||||
propertyPath: m_RootOrder
|
propertyPath: m_RootOrder
|
||||||
value: 15
|
value: 14
|
||||||
objectReference: {fileID: 0}
|
objectReference: {fileID: 0}
|
||||||
- target: {fileID: 5088247503209915273, guid: f18510934c4581d47819abfbf1bd3647,
|
- target: {fileID: 5088247503209915273, guid: f18510934c4581d47819abfbf1bd3647,
|
||||||
type: 3}
|
type: 3}
|
||||||
|
@ -13128,7 +13039,7 @@ PrefabInstance:
|
||||||
- target: {fileID: 4305911198204250499, guid: 08bf595b66a0f9347973cbccd7039436,
|
- target: {fileID: 4305911198204250499, guid: 08bf595b66a0f9347973cbccd7039436,
|
||||||
type: 3}
|
type: 3}
|
||||||
propertyPath: m_RootOrder
|
propertyPath: m_RootOrder
|
||||||
value: 20
|
value: 19
|
||||||
objectReference: {fileID: 0}
|
objectReference: {fileID: 0}
|
||||||
- target: {fileID: 4305911198204250499, guid: 08bf595b66a0f9347973cbccd7039436,
|
- target: {fileID: 4305911198204250499, guid: 08bf595b66a0f9347973cbccd7039436,
|
||||||
type: 3}
|
type: 3}
|
||||||
|
@ -13202,7 +13113,7 @@ PrefabInstance:
|
||||||
- target: {fileID: 2925653066038063199, guid: c7d364eea8941e847b69eba0d43e22b6,
|
- target: {fileID: 2925653066038063199, guid: c7d364eea8941e847b69eba0d43e22b6,
|
||||||
type: 3}
|
type: 3}
|
||||||
propertyPath: m_RootOrder
|
propertyPath: m_RootOrder
|
||||||
value: 28
|
value: 27
|
||||||
objectReference: {fileID: 0}
|
objectReference: {fileID: 0}
|
||||||
- target: {fileID: 2925653066038063199, guid: c7d364eea8941e847b69eba0d43e22b6,
|
- target: {fileID: 2925653066038063199, guid: c7d364eea8941e847b69eba0d43e22b6,
|
||||||
type: 3}
|
type: 3}
|
||||||
|
@ -13271,7 +13182,7 @@ PrefabInstance:
|
||||||
- target: {fileID: 8889410696358529550, guid: bc90096cf6047474a8195137fb77e890,
|
- target: {fileID: 8889410696358529550, guid: bc90096cf6047474a8195137fb77e890,
|
||||||
type: 3}
|
type: 3}
|
||||||
propertyPath: m_RootOrder
|
propertyPath: m_RootOrder
|
||||||
value: 33
|
value: 31
|
||||||
objectReference: {fileID: 0}
|
objectReference: {fileID: 0}
|
||||||
- target: {fileID: 8889410696358529550, guid: bc90096cf6047474a8195137fb77e890,
|
- target: {fileID: 8889410696358529550, guid: bc90096cf6047474a8195137fb77e890,
|
||||||
type: 3}
|
type: 3}
|
||||||
|
@ -13340,7 +13251,7 @@ PrefabInstance:
|
||||||
- target: {fileID: 8345163905356490183, guid: 405a2254073206e42bbe8aad0088a501,
|
- target: {fileID: 8345163905356490183, guid: 405a2254073206e42bbe8aad0088a501,
|
||||||
type: 3}
|
type: 3}
|
||||||
propertyPath: m_RootOrder
|
propertyPath: m_RootOrder
|
||||||
value: 27
|
value: 26
|
||||||
objectReference: {fileID: 0}
|
objectReference: {fileID: 0}
|
||||||
- target: {fileID: 8345163905356490183, guid: 405a2254073206e42bbe8aad0088a501,
|
- target: {fileID: 8345163905356490183, guid: 405a2254073206e42bbe8aad0088a501,
|
||||||
type: 3}
|
type: 3}
|
||||||
|
|
|
@ -11,7 +11,8 @@
|
||||||
"GUID:f263169dea78d2249ba035c363b9cb8e",
|
"GUID:f263169dea78d2249ba035c363b9cb8e",
|
||||||
"GUID:ea5474181b324dd49a5976cd68f44f18",
|
"GUID:ea5474181b324dd49a5976cd68f44f18",
|
||||||
"GUID:d8b63aba1907145bea998dd612889d6b",
|
"GUID:d8b63aba1907145bea998dd612889d6b",
|
||||||
"GUID:900280954c76a0d41bc47cef37f91107"
|
"GUID:900280954c76a0d41bc47cef37f91107",
|
||||||
|
"GUID:49b49c76ee64f6b41bf28ef951cb0e50"
|
||||||
],
|
],
|
||||||
"includePlatforms": [],
|
"includePlatforms": [],
|
||||||
"excludePlatforms": [],
|
"excludePlatforms": [],
|
||||||
|
|
|
@ -31,7 +31,11 @@ namespace BITFALL
|
||||||
[Header(Constant.Header.Settings)]
|
[Header(Constant.Header.Settings)]
|
||||||
public LayerMask layerMask;
|
public LayerMask layerMask;
|
||||||
[Header(Constant.Header.Prefabs)]
|
[Header(Constant.Header.Prefabs)]
|
||||||
public ObjectMaterialScriptableObject defaultMaterial;
|
[SerializeField] private ObjectMaterialScriptableObject defaultMaterial;
|
||||||
|
|
||||||
|
[Header(Constant.Header.Providers)]
|
||||||
|
[SerializeField, SerializeReference, SubclassSelector]
|
||||||
|
private INetProvider netProvider;
|
||||||
[Header(Constant.Header.Settings)]
|
[Header(Constant.Header.Settings)]
|
||||||
public UnityPool<BITBullet> pool = new();
|
public UnityPool<BITBullet> pool = new();
|
||||||
[Header(Constant.Header.InternalVariables)]
|
[Header(Constant.Header.InternalVariables)]
|
||||||
|
@ -39,8 +43,6 @@ namespace BITFALL
|
||||||
void Start()
|
void Start()
|
||||||
{
|
{
|
||||||
Spawn += SpawnBullet;
|
Spawn += SpawnBullet;
|
||||||
|
|
||||||
DI.Get<ClientBase>().AddRpcHandle(this);
|
|
||||||
}
|
}
|
||||||
void OnDestroy()
|
void OnDestroy()
|
||||||
{
|
{
|
||||||
|
@ -141,6 +143,7 @@ namespace BITFALL
|
||||||
//DI.Get<ClientBase>().SendRT(nameof(RpcSpawnBullet), x);
|
//DI.Get<ClientBase>().SendRT(nameof(RpcSpawnBullet), x);
|
||||||
//FGame.ClientAllRpc(nameof(RpcSpawnBullet), x);
|
//FGame.ClientAllRpc(nameof(RpcSpawnBullet), x);
|
||||||
//DI.Get<INetMessager>().Send<SpawnBullet>(x);
|
//DI.Get<INetMessager>().Send<SpawnBullet>(x);
|
||||||
|
netProvider.ServerCommand(x);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -82,7 +82,7 @@ namespace BITFALL.Entites
|
||||||
{
|
{
|
||||||
lookInput = MathV.TransientRotationAxis(transform.eulerAngles);
|
lookInput = MathV.TransientRotationAxis(transform.eulerAngles);
|
||||||
}
|
}
|
||||||
public override async void OnStart()
|
public override void OnStart()
|
||||||
{
|
{
|
||||||
foreach (var state in characterStates)
|
foreach (var state in characterStates)
|
||||||
{
|
{
|
||||||
|
@ -99,9 +99,6 @@ namespace BITFALL.Entites
|
||||||
inputActionGroup.RegisterCallback(crouchAction, OnCrouch);
|
inputActionGroup.RegisterCallback(crouchAction, OnCrouch);
|
||||||
|
|
||||||
entity.AddListener<IMovementCancelAction>(CancelMovement);
|
entity.AddListener<IMovementCancelAction>(CancelMovement);
|
||||||
|
|
||||||
client = await DI.GetAsync<ClientBase>();
|
|
||||||
client.AddRpcHandle(this);
|
|
||||||
}
|
}
|
||||||
public override void OnSpawn()
|
public override void OnSpawn()
|
||||||
{
|
{
|
||||||
|
|
|
@ -1,3 +1,4 @@
|
||||||
|
using System;
|
||||||
using System.Collections;
|
using System.Collections;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using UnityEngine;
|
using UnityEngine;
|
||||||
|
@ -7,20 +8,22 @@ using BITKit;
|
||||||
using BITKit.Entities;
|
using BITKit.Entities;
|
||||||
using BITKit.SubSystems;
|
using BITKit.SubSystems;
|
||||||
using Net.Share;
|
using Net.Share;
|
||||||
|
using Unity.Mathematics;
|
||||||
namespace BITFALL
|
namespace BITFALL
|
||||||
{
|
{
|
||||||
public class MovementService : SubBITSystem
|
public class KinematicMovementService : MonoBehaviour
|
||||||
{
|
{
|
||||||
public override void OnCreate()
|
[SerializeField, SerializeReference, SubclassSelector]
|
||||||
|
private INetProvider netProvider;
|
||||||
|
private void Start()
|
||||||
{
|
{
|
||||||
BITNet.AddRpcHandle(this);
|
|
||||||
}
|
}
|
||||||
[Rpc]
|
public void SyncMovement(int entityId, float3 currentVelocity, float3 currentPos,quaternion currentRot,bool isGrounded)
|
||||||
public void SyncMovement(int entityId, Net.Vector3 currentVelocity, Net.Vector3 currentPos,Net.Quaternion currentRot,bool isGrounded)
|
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
EntitiesManager
|
UnityEntitiesManager
|
||||||
.GetOrAdd(entityId)
|
.GetOrAdd(entityId)
|
||||||
.Get<IEntityMovement>()
|
.Get<IEntityMovement>()
|
||||||
.SyncMovement(currentVelocity, currentPos, currentRot,isGrounded);
|
.SyncMovement(currentVelocity, currentPos, currentRot,isGrounded);
|
||||||
|
@ -28,7 +31,7 @@ namespace BITFALL
|
||||||
catch (System.Exception e)
|
catch (System.Exception e)
|
||||||
{
|
{
|
||||||
StringBuilder stringBuilder = new();
|
StringBuilder stringBuilder = new();
|
||||||
var entity = EntitiesManager.GetOrAdd(entityId);
|
var entity = UnityEntitiesManager.GetOrAdd(entityId);
|
||||||
stringBuilder.AppendLine($"Entity:{entityId}@{entity}");
|
stringBuilder.AppendLine($"Entity:{entityId}@{entity}");
|
||||||
var movement = entity.Get<IEntityMovement>();
|
var movement = entity.Get<IEntityMovement>();
|
||||||
stringBuilder.AppendLine($"Movement@{movement}");
|
stringBuilder.AppendLine($"Movement@{movement}");
|
|
@ -1,32 +0,0 @@
|
||||||
using System.Collections;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using UnityEngine;
|
|
||||||
using Net.Share;
|
|
||||||
using BITKit;
|
|
||||||
using BITKit.Entities;
|
|
||||||
using Net.Client;
|
|
||||||
namespace BITFALL.Entites
|
|
||||||
{
|
|
||||||
[CreateOnStart(BITAppForUnity.Path.Services,nameof(NetEntitesManager))]
|
|
||||||
public class NetEntitesManager : MonoBehaviour
|
|
||||||
{
|
|
||||||
public Entity proxy;
|
|
||||||
async void Start()
|
|
||||||
{
|
|
||||||
EntitiesManager.CreateFactory = CreateFactory;
|
|
||||||
var client = await DI.GetAsync<ClientBase>();
|
|
||||||
client.AddRpcHandle(this);
|
|
||||||
}
|
|
||||||
[Rpc]
|
|
||||||
public void RpcEntityHeartbeat(int entityId)
|
|
||||||
{
|
|
||||||
var entity = EntitiesManager.GetOrAdd(entityId, CreateFactory);
|
|
||||||
}
|
|
||||||
IEntity CreateFactory(int id)
|
|
||||||
{
|
|
||||||
var entity = Instantiate(proxy);
|
|
||||||
entity.Id = id;
|
|
||||||
return entity;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -11,11 +11,15 @@ namespace BITFALL.Entites
|
||||||
{
|
{
|
||||||
public class EntityGDNetPlayer : EntityComponent
|
public class EntityGDNetPlayer : EntityComponent
|
||||||
{
|
{
|
||||||
|
[SerializeField, SerializeReference, SubclassSelector]
|
||||||
|
private INetClient netClient;
|
||||||
|
[SerializeField, SerializeReference, SubclassSelector]
|
||||||
|
private INetProvider netProvider;
|
||||||
public override void OnStart()
|
public override void OnStart()
|
||||||
{
|
{
|
||||||
entity.Id = Guid.NewGuid().GetHashCode();
|
entity.Id = Guid.NewGuid().GetHashCode();
|
||||||
BITNet.OnConnected+=OnConnected;
|
netClient.OnConnected+=OnConnected;
|
||||||
BITNet.OnDisconnect += OnDisconnect;
|
netClient.OnDisconnected += OnDisconnect;
|
||||||
IEntity.LocalPlayer = entity;
|
IEntity.LocalPlayer = entity;
|
||||||
IEntity.OnSpawnLocalPlayer(entity);
|
IEntity.OnSpawnLocalPlayer(entity);
|
||||||
}
|
}
|
||||||
|
|
|
@ -13,7 +13,6 @@ namespace BITFALL.Entites
|
||||||
{
|
{
|
||||||
public override void OnCreate()
|
public override void OnCreate()
|
||||||
{
|
{
|
||||||
BITNet.AddRpcHandle(this);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -8,8 +8,7 @@
|
||||||
"GUID:eaaac13fa1ccdfb4ca5d246fb1d9c561",
|
"GUID:eaaac13fa1ccdfb4ca5d246fb1d9c561",
|
||||||
"GUID:be17a8778dbfe454890ed8279279e153",
|
"GUID:be17a8778dbfe454890ed8279279e153",
|
||||||
"GUID:49b49c76ee64f6b41bf28ef951cb0e50",
|
"GUID:49b49c76ee64f6b41bf28ef951cb0e50",
|
||||||
"GUID:9400d40641bab5b4a9702f65bf5c6eb5",
|
"GUID:1bb4187526a9431478feccaef064696a"
|
||||||
"GUID:53336df3122d0cb41a64b6109d19b016"
|
|
||||||
],
|
],
|
||||||
"includePlatforms": [],
|
"includePlatforms": [],
|
||||||
"excludePlatforms": [],
|
"excludePlatforms": [],
|
||||||
|
|
|
@ -1,48 +0,0 @@
|
||||||
using System;
|
|
||||||
using System.Collections;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using Net.Server;
|
|
||||||
using System.Data.SqlTypes;
|
|
||||||
using System.IO;
|
|
||||||
using Net.Serialize;
|
|
||||||
using BITKit;
|
|
||||||
using Net.Share;
|
|
||||||
using Unity.Plastic.Antlr3.Runtime.Misc;
|
|
||||||
|
|
||||||
namespace BITFALL.Services
|
|
||||||
{
|
|
||||||
[System.Serializable]
|
|
||||||
public record PlayerModel
|
|
||||||
{
|
|
||||||
public int Id;
|
|
||||||
public string Name;
|
|
||||||
public string PlayerId;
|
|
||||||
}
|
|
||||||
|
|
||||||
public class PlayerModelBinary : NetMessageReader<PlayerModel>
|
|
||||||
{
|
|
||||||
public override PlayerModel ReadBinary(BinaryReader reader)
|
|
||||||
{
|
|
||||||
return new PlayerModel
|
|
||||||
{
|
|
||||||
Id = reader.ReadInt32(),
|
|
||||||
Name = reader.ReadString(),
|
|
||||||
PlayerId = reader.ReadString()
|
|
||||||
};
|
|
||||||
}
|
|
||||||
public override void WriteBinary(BinaryWriter writer, PlayerModel value)
|
|
||||||
{
|
|
||||||
writer.Write(value.Id);
|
|
||||||
writer.Write(value.Name);
|
|
||||||
writer.Write(value.PlayerId);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
public interface IPlayerService
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
public struct PlayerReadyCommand
|
|
||||||
{
|
|
||||||
public int PlayerId;
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -4,29 +4,57 @@ using System.Collections.Generic;
|
||||||
using BITFALL.Services;
|
using BITFALL.Services;
|
||||||
using BITKit;
|
using BITKit;
|
||||||
using BITKit.HttpNet;
|
using BITKit.HttpNet;
|
||||||
|
using BITKit.Steamwork;
|
||||||
using BITKit.SubSystems;
|
using BITKit.SubSystems;
|
||||||
using Net.Client;
|
using Net.Client;
|
||||||
using Net.Server;
|
using Net.Server;
|
||||||
using Net.Share;
|
using Net.Share;
|
||||||
using UnityEngine;
|
using UnityEngine;
|
||||||
using Cysharp.Threading.Tasks;
|
using Cysharp.Threading.Tasks;
|
||||||
|
using INetClient = BITKit.INetClient;
|
||||||
|
|
||||||
namespace BITFALL
|
namespace BITFALL
|
||||||
{
|
{
|
||||||
public class UnityPlayerService : MonoBehaviour, IPlayerService
|
public class UnityPlayerService : MonoBehaviour, IPlayerService
|
||||||
{
|
{
|
||||||
public event Action<int> OnPlayerReady;
|
//申明服务
|
||||||
[SerializeField, SerializeReference, SubclassSelector]
|
[SerializeField, SerializeReference, SubclassSelector]
|
||||||
private INetProvider netProvider;
|
private INetProvider netProvider;
|
||||||
|
[SerializeField, SerializeReference, SubclassSelector]
|
||||||
|
private INetClient netClient;
|
||||||
|
[SerializeField, SerializeReference, SubclassSelector]
|
||||||
|
private ISteamService steamService;
|
||||||
|
//接口实现
|
||||||
|
public event Action<PlayerModel> OnVerifyPlayer;
|
||||||
|
public event Action<PlayerModel> OnPlayerVerified;
|
||||||
private void Start()
|
private void Start()
|
||||||
{
|
{
|
||||||
netProvider.AddRpcHandle(this);
|
netProvider.AddRpcHandle(this);
|
||||||
BITNet.OnConnected += OnConnect;
|
netClient.OnConnected += OnConnect;
|
||||||
|
|
||||||
|
netProvider.AddCommandListener<PlayerVerifiedCommand>(OnPlayerVerifiedCallback);
|
||||||
}
|
}
|
||||||
private void OnConnect()
|
private void OnConnect()
|
||||||
{
|
{
|
||||||
OnPlayerReady?.Invoke(0);
|
var command = new PlayerVerifiedCommand()
|
||||||
|
{
|
||||||
|
PlayerModel = new PlayerModel
|
||||||
|
{
|
||||||
|
Id =netClient.Id,
|
||||||
|
SteamId =steamService.SteamId,
|
||||||
|
Name = steamService.Name,
|
||||||
|
}
|
||||||
|
};
|
||||||
|
BIT4Log.Log<UnityPlayerService>("正在发送玩家验证清单");
|
||||||
|
|
||||||
|
OnVerifyPlayer?.Invoke(command.PlayerModel);
|
||||||
|
|
||||||
|
netProvider.ServerCommand(command);
|
||||||
|
}
|
||||||
|
private void OnPlayerVerifiedCallback(PlayerVerifiedCommand command)
|
||||||
|
{
|
||||||
|
BIT4Log.Log<UnityPlayerService>($"玩家\t{command.PlayerModel.Name}\t已验证");
|
||||||
|
OnPlayerVerified?.Invoke(command.PlayerModel);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -18,8 +18,7 @@
|
||||||
"GUID:eaaac13fa1ccdfb4ca5d246fb1d9c561",
|
"GUID:eaaac13fa1ccdfb4ca5d246fb1d9c561",
|
||||||
"GUID:66d2ae14764cc7d49aad4b16930747c0",
|
"GUID:66d2ae14764cc7d49aad4b16930747c0",
|
||||||
"GUID:e531122bce810cf4a9184a5c27251bf8",
|
"GUID:e531122bce810cf4a9184a5c27251bf8",
|
||||||
"GUID:9400d40641bab5b4a9702f65bf5c6eb5",
|
"GUID:49b49c76ee64f6b41bf28ef951cb0e50"
|
||||||
"GUID:53336df3122d0cb41a64b6109d19b016"
|
|
||||||
],
|
],
|
||||||
"includePlatforms": [],
|
"includePlatforms": [],
|
||||||
"excludePlatforms": [],
|
"excludePlatforms": [],
|
||||||
|
|
|
@ -6,12 +6,15 @@ using UnityEngine.InputSystem;
|
||||||
using BITKit;
|
using BITKit;
|
||||||
using BITKit.UX;
|
using BITKit.UX;
|
||||||
using BITKit.Entities;
|
using BITKit.Entities;
|
||||||
using Net.Share;
|
|
||||||
using Net.Client;
|
|
||||||
namespace BITFALL.UX
|
namespace BITFALL.UX
|
||||||
{
|
{
|
||||||
public class HUD : UXPanel, ISelectableCallback
|
public class HUD : UXPanel, ISelectableCallback
|
||||||
{
|
{
|
||||||
|
[Header(Constant.Header.Providers)]
|
||||||
|
[SerializeField, SerializeReference, SubclassSelector]
|
||||||
|
private INetClient netClient;
|
||||||
|
[SerializeField, SerializeReference, SubclassSelector]
|
||||||
|
private INetProvider netProvider;
|
||||||
[Header(Constant.Header.Input)]
|
[Header(Constant.Header.Input)]
|
||||||
public InputActionReference inventoryAction;
|
public InputActionReference inventoryAction;
|
||||||
public InputActionReference returnAction;
|
public InputActionReference returnAction;
|
||||||
|
@ -24,7 +27,7 @@ namespace BITFALL.UX
|
||||||
inputActionGroup.RegisterCallback(returnAction, OnReturn);
|
inputActionGroup.RegisterCallback(returnAction, OnReturn);
|
||||||
inputActionGroup.RegisterCallback(inventoryAction, OnInventry);
|
inputActionGroup.RegisterCallback(inventoryAction, OnInventry);
|
||||||
|
|
||||||
BITNet.OnConnected += OnConnected;
|
netClient.OnConnected += OnConnected;
|
||||||
}
|
}
|
||||||
public override void Set(bool active)
|
public override void Set(bool active)
|
||||||
{
|
{
|
||||||
|
|
|
@ -6,12 +6,16 @@ using UnityEngine.InputSystem;
|
||||||
using BITKit;
|
using BITKit;
|
||||||
using BITKit.UX;
|
using BITKit.UX;
|
||||||
using BITKit.Entities;
|
using BITKit.Entities;
|
||||||
using Net.Client;
|
|
||||||
using Net.Share;
|
|
||||||
namespace BITFALL.UX
|
namespace BITFALL.UX
|
||||||
{
|
{
|
||||||
public class Loading : UXPanel
|
public class Loading : UXPanel
|
||||||
{
|
{
|
||||||
|
[Header(Constant.Header.Providers)]
|
||||||
|
[SerializeField, SerializeReference, SubclassSelector]
|
||||||
|
private INetClient netClient;
|
||||||
|
[SerializeField, SerializeReference, SubclassSelector]
|
||||||
|
private INetProvider netProvider;
|
||||||
|
[Header(Constant.Header.Components)]
|
||||||
public UXBar loadBar;
|
public UXBar loadBar;
|
||||||
public UXLabel loadText;
|
public UXLabel loadText;
|
||||||
public override void OnStart()
|
public override void OnStart()
|
||||||
|
@ -19,15 +23,15 @@ namespace BITFALL.UX
|
||||||
base.OnStart();
|
base.OnStart();
|
||||||
//DI.Get<ClientBase>().AddStateHandler(NetworkState.Connected, OnConnected);
|
//DI.Get<ClientBase>().AddStateHandler(NetworkState.Connected, OnConnected);
|
||||||
//DI.Get<ClientBase>().AddStateHandler(NetworkState.TryToConnect, OnStartConnect);
|
//DI.Get<ClientBase>().AddStateHandler(NetworkState.TryToConnect, OnStartConnect);
|
||||||
BITNet.OnTryToConnect += OnStartConnect;
|
netClient.OnStartConnect += OnStartConnect;
|
||||||
Data.AddListener<IProgress>(OnLoadProgress);
|
Data.AddListener<IProgress>(OnLoadProgress);
|
||||||
BITNet.OnStartConnect += OnStartConnect;
|
|
||||||
}
|
}
|
||||||
void OnStartConnect()
|
private void OnStartConnect()
|
||||||
{
|
{
|
||||||
|
loadBar.SetDirect(0,"正在开始加载");
|
||||||
UXFramework.Enter<Loading>();
|
UXFramework.Enter<Loading>();
|
||||||
}
|
}
|
||||||
void OnLoadProgress(IProgress progress)
|
private void OnLoadProgress(IProgress progress)
|
||||||
{
|
{
|
||||||
loadBar.Set(progress.Progress);
|
loadBar.Set(progress.Progress);
|
||||||
loadText.Set(progress.Message);
|
loadText.Set(progress.Message);
|
||||||
|
|
|
@ -7,10 +7,16 @@ using BITKit.UX;
|
||||||
using Net;
|
using Net;
|
||||||
using Net.Client;
|
using Net.Client;
|
||||||
using Net.Share;
|
using Net.Share;
|
||||||
|
using INetClient = BITKit.INetClient;
|
||||||
|
|
||||||
namespace BITFALL.UX
|
namespace BITFALL.UX
|
||||||
{
|
{
|
||||||
public class Menu : UXPanel
|
public class Menu : UXPanel
|
||||||
{
|
{
|
||||||
|
[Header(Constant.Header.Providers)]
|
||||||
|
[SerializeField, SerializeReference, SubclassSelector]
|
||||||
|
private INetClient netClient;
|
||||||
|
[SerializeField, SerializeReference, SubclassSelector]
|
||||||
[Header(Constant.Header.Components)]
|
[Header(Constant.Header.Components)]
|
||||||
public UXButton connectButton;
|
public UXButton connectButton;
|
||||||
public UXButton localhostButton;
|
public UXButton localhostButton;
|
||||||
|
@ -23,10 +29,9 @@ namespace BITFALL.UX
|
||||||
public override void OnStart()
|
public override void OnStart()
|
||||||
{
|
{
|
||||||
base.OnStart();
|
base.OnStart();
|
||||||
BITNet.OnConnected += OnConnected;
|
|
||||||
BITNet.OnConnectLost += OnDisconnect;
|
netClient.OnConnected += OnConnected;
|
||||||
BITNet.OnConnectLost += OnDisconnect;
|
netClient.OnConnectedFailed += OnDisconnect;
|
||||||
BITNet.OnConnectFailed += OnDisconnect;
|
|
||||||
|
|
||||||
inputActionGroup.RegisterCallback(returnAction, OnReturn);
|
inputActionGroup.RegisterCallback(returnAction, OnReturn);
|
||||||
|
|
||||||
|
@ -39,17 +44,17 @@ namespace BITFALL.UX
|
||||||
}
|
}
|
||||||
public void StartIntelnetConnect()
|
public void StartIntelnetConnect()
|
||||||
{
|
{
|
||||||
DI.Get<BITNet>().ConnectToServer();
|
netClient.Connect();
|
||||||
}
|
}
|
||||||
public void StartLocalConnect()
|
public void StartLocalConnect()
|
||||||
{
|
{
|
||||||
DI.Get<BITNet>().ConnectToLocal();
|
netClient.Connect("localhost");
|
||||||
}
|
}
|
||||||
public void Disconnect()
|
public void Disconnect()
|
||||||
{
|
{
|
||||||
DI.Get<BITNet>().Disconnect();
|
netClient.Disconnect();
|
||||||
}
|
}
|
||||||
public void OnConnected()
|
private void OnConnected()
|
||||||
{
|
{
|
||||||
connectButton.SetEnabled(true);
|
connectButton.SetEnabled(true);
|
||||||
localhostButton.SetEnabled(true);
|
localhostButton.SetEnabled(true);
|
||||||
|
@ -60,19 +65,19 @@ namespace BITFALL.UX
|
||||||
disconnectButton.SetActive(true);
|
disconnectButton.SetActive(true);
|
||||||
backgroundImage.SetActive(false);
|
backgroundImage.SetActive(false);
|
||||||
}
|
}
|
||||||
public void OnConnectFailed()
|
private void OnConnectFailed()
|
||||||
{
|
{
|
||||||
UXFramework.Enter<Menu>();
|
UXFramework.Enter<Menu>();
|
||||||
connectButton.SetEnabled(true);
|
connectButton.SetEnabled(true);
|
||||||
localhostButton.SetEnabled(true);
|
localhostButton.SetEnabled(true);
|
||||||
OnDisconnected();
|
OnDisconnected();
|
||||||
}
|
}
|
||||||
public void OnStartConnect()
|
private void OnStartConnect()
|
||||||
{
|
{
|
||||||
connectButton.SetEnabled(false);
|
connectButton.SetEnabled(false);
|
||||||
localhostButton.SetEnabled(false);
|
localhostButton.SetEnabled(false);
|
||||||
}
|
}
|
||||||
public void OnDisconnected()
|
private void OnDisconnected()
|
||||||
{
|
{
|
||||||
returnButton.SetActive(false);
|
returnButton.SetActive(false);
|
||||||
connectButton.SetActive(true);
|
connectButton.SetActive(true);
|
||||||
|
@ -80,19 +85,18 @@ namespace BITFALL.UX
|
||||||
disconnectButton.SetActive(false);
|
disconnectButton.SetActive(false);
|
||||||
backgroundImage.SetActive(true);
|
backgroundImage.SetActive(true);
|
||||||
}
|
}
|
||||||
void OnDisconnect()
|
private void OnDisconnect()
|
||||||
{
|
{
|
||||||
BIT4Log.Log<Menu>("正在尝试返回到主菜单");
|
|
||||||
UXFramework.Enter<Menu>();
|
UXFramework.Enter<Menu>();
|
||||||
OnDisconnected();
|
OnDisconnected();
|
||||||
}
|
}
|
||||||
void OnReturn(InputAction.CallbackContext context)
|
private void OnReturn(InputAction.CallbackContext context)
|
||||||
{
|
{
|
||||||
/* if (ClientManager.Instance.client.Connected)
|
if (!netClient.IsConnected) return;
|
||||||
if (context.ReadValueAsButton())
|
if (context.ReadValueAsButton())
|
||||||
{
|
{
|
||||||
UXFramework.Enter<HUD>();
|
UXFramework.Enter<HUD>();
|
||||||
} */
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -8,12 +8,7 @@
|
||||||
<ui:Button text="进入战区" display-tooltip-when-elided="true" name="play-button" class="navigation" />
|
<ui:Button text="进入战区" display-tooltip-when-elided="true" name="play-button" class="navigation" />
|
||||||
<ui:Button text="饰品库存" display-tooltip-when-elided="true" name="inventory-button" class="navigation" />
|
<ui:Button text="饰品库存" display-tooltip-when-elided="true" name="inventory-button" class="navigation" />
|
||||||
<ui:Button text="情报中心" display-tooltip-when-elided="true" name="information-button" class="navigation" />
|
<ui:Button text="情报中心" display-tooltip-when-elided="true" name="information-button" class="navigation" />
|
||||||
<ui:VisualElement style="position: absolute; top: 0; bottom: 0; right: 32px; justify-content: center;">
|
<ui:Button text="退出" display-tooltip-when-elided="true" name="exit-button" class="navigation" style="flex-grow: 1; position: absolute; top: 0; right: 0; bottom: 0;" />
|
||||||
<ui:Button display-tooltip-when-elided="true" name="exit-button" class="return-button dark">
|
|
||||||
<ui:VisualElement name="icon-image" />
|
|
||||||
<ui:Label text="退出" display-tooltip-when-elided="true" name="context-label" />
|
|
||||||
</ui:Button>
|
|
||||||
</ui:VisualElement>
|
|
||||||
</ui:VisualElement>
|
</ui:VisualElement>
|
||||||
<ui:VisualElement name="windows" class="root" style="left: 64px; top: 128px; right: 64px; bottom: 64px;">
|
<ui:VisualElement name="windows" class="root" style="left: 64px; top: 128px; right: 64px; bottom: 64px;">
|
||||||
<ui:VisualElement name="play-window">
|
<ui:VisualElement name="play-window">
|
||||||
|
|
|
@ -1,10 +1,8 @@
|
||||||
{
|
{
|
||||||
"name": "BITFALL.PlayerService.Core",
|
"name": "BITFALL.Player.Core",
|
||||||
"rootNamespace": "",
|
"rootNamespace": "",
|
||||||
"references": [
|
"references": [
|
||||||
"GUID:14fe60d984bf9f84eac55c6ea033a8f4",
|
"GUID:14fe60d984bf9f84eac55c6ea033a8f4"
|
||||||
"GUID:f263169dea78d2249ba035c363b9cb8e",
|
|
||||||
"GUID:9400d40641bab5b4a9702f65bf5c6eb5"
|
|
||||||
],
|
],
|
||||||
"includePlatforms": [],
|
"includePlatforms": [],
|
||||||
"excludePlatforms": [],
|
"excludePlatforms": [],
|
|
@ -0,0 +1,29 @@
|
||||||
|
using System;
|
||||||
|
using System.IO;
|
||||||
|
using BITKit;
|
||||||
|
|
||||||
|
namespace BITFALL.Services
|
||||||
|
{
|
||||||
|
[Serializable]
|
||||||
|
public record PlayerModel
|
||||||
|
{
|
||||||
|
public int Id;
|
||||||
|
public string Name = "anonymous";
|
||||||
|
public ulong SteamId;
|
||||||
|
}
|
||||||
|
public interface IPlayerService
|
||||||
|
{
|
||||||
|
event Action<PlayerModel> OnVerifyPlayer;
|
||||||
|
event Action<PlayerModel> OnPlayerVerified;
|
||||||
|
}
|
||||||
|
[Serializable]
|
||||||
|
public record VerifyPlayerCommand
|
||||||
|
{
|
||||||
|
public PlayerModel PlayerModel;
|
||||||
|
}
|
||||||
|
[Serializable]
|
||||||
|
public record PlayerVerifiedCommand
|
||||||
|
{
|
||||||
|
public PlayerModel PlayerModel;
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,253 +0,0 @@
|
||||||
using System;
|
|
||||||
using System.Collections;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using UnityEngine;
|
|
||||||
using BITKit;
|
|
||||||
using BITKit.UX;
|
|
||||||
using BITKit.HttpNet;
|
|
||||||
using Cysharp.Threading.Tasks;
|
|
||||||
using Net.Client;
|
|
||||||
using UnityEngine.UIElements;
|
|
||||||
using System.Text;
|
|
||||||
using Net.Share;
|
|
||||||
using Object = System.Object;
|
|
||||||
|
|
||||||
namespace BITKit
|
|
||||||
{
|
|
||||||
public interface INetClientProvider
|
|
||||||
{
|
|
||||||
ClientBase GetClient();
|
|
||||||
}
|
|
||||||
//[CreateOnStart(BITAppForUnity.Path.Services,nameof(BITNet))]
|
|
||||||
public class BITNet : MonoBehaviour
|
|
||||||
{
|
|
||||||
[UnityEngine.RuntimeInitializeOnLoadMethod]
|
|
||||||
static void Reload()
|
|
||||||
{
|
|
||||||
OnStartConnect = null;
|
|
||||||
OnConnected = null;
|
|
||||||
OnConnectFailed = null;
|
|
||||||
OnTryToConnect = null;
|
|
||||||
OnTryToConnectFailed = null;
|
|
||||||
OnDisconnect = null;
|
|
||||||
OnConnectLost = null;
|
|
||||||
OnConnection = null;
|
|
||||||
OnReconnect = null;
|
|
||||||
OnOnWhenQueuing = null;
|
|
||||||
OnOnQueueCancellation = null;
|
|
||||||
RpcHandles.Clear();
|
|
||||||
}
|
|
||||||
public static event Action OnStartConnect;
|
|
||||||
public static event Action OnConnected;
|
|
||||||
public static event Action OnConnectFailed;
|
|
||||||
public static event Action OnTryToConnect;
|
|
||||||
public static event Action OnTryToConnectFailed;
|
|
||||||
public static event Action OnDisconnect;
|
|
||||||
public static event Action OnConnectLost;
|
|
||||||
public static event Action OnConnection;
|
|
||||||
public static event Action OnReconnect;
|
|
||||||
public static event Action OnOnWhenQueuing;
|
|
||||||
public static event Action OnOnQueueCancellation;
|
|
||||||
|
|
||||||
private static BITNet Singleton;
|
|
||||||
private static readonly List<object> RpcHandles = new();
|
|
||||||
private static readonly Queue<(string name,Object[] pars)> Rpcs = new();
|
|
||||||
[BITCommand]
|
|
||||||
public static void Connect(string address, int port)
|
|
||||||
{
|
|
||||||
Singleton.ConnectInternal(address, port);
|
|
||||||
}
|
|
||||||
public static Action<object> AddRpcHandle => RpcHandles.Add;
|
|
||||||
public static void SendRT(string rpcName, params object[] pars)
|
|
||||||
{
|
|
||||||
Rpcs.Enqueue(new()
|
|
||||||
{
|
|
||||||
name = rpcName,
|
|
||||||
pars = pars
|
|
||||||
});
|
|
||||||
}
|
|
||||||
[Header(Constant.Header.Settings)]
|
|
||||||
public string address = "localhost";
|
|
||||||
public int port = 666;
|
|
||||||
public int apiPort = 27014;
|
|
||||||
[Header(Constant.Header.Settings)]
|
|
||||||
[SerializeReference, SubclassSelector] public IWebProvider webProvider;
|
|
||||||
[SerializeReference, SubclassSelector] public INetClientProvider clientProvider;
|
|
||||||
[Header(Constant.Header.InternalVariables)]
|
|
||||||
ClientBase client;
|
|
||||||
private string GetApiUrl(string address) => $"http://{address}:{apiPort}/api";
|
|
||||||
public string GetAPI(params string[] path)
|
|
||||||
{
|
|
||||||
return GetApiUrl(address) + "/" + String.Join("/", path);
|
|
||||||
}
|
|
||||||
[BIT]
|
|
||||||
public void ConnectToServer()
|
|
||||||
{
|
|
||||||
ConnectInternal(address, port);
|
|
||||||
}
|
|
||||||
[BIT]
|
|
||||||
public void ConnectToLocal()
|
|
||||||
{
|
|
||||||
ConnectInternal("localhost", port);
|
|
||||||
}
|
|
||||||
[BIT]
|
|
||||||
public void Disconnect()
|
|
||||||
{
|
|
||||||
client.Close();
|
|
||||||
//clientManager.client.Close();
|
|
||||||
}
|
|
||||||
async void ConnectInternal(string address, int port)
|
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
|
||||||
foreach (var x in RpcHandles)
|
|
||||||
{
|
|
||||||
client.AddRpcHandle(x);
|
|
||||||
}
|
|
||||||
|
|
||||||
OnStartConnect?.Invoke();
|
|
||||||
var message = $"正在获取api:{GetApiUrl(address)}";
|
|
||||||
|
|
||||||
Data.Set<IProgress>(new ProgressInfo()
|
|
||||||
{
|
|
||||||
Progress = 0.1f,
|
|
||||||
Message = message,
|
|
||||||
});
|
|
||||||
|
|
||||||
Debug.Log(message);
|
|
||||||
await webProvider
|
|
||||||
.GetAsync<Package>(GetApiUrl(address),this.GetCancellationTokenOnDestroy());
|
|
||||||
|
|
||||||
message = $"已获取到服务器信息,正在连接到服务器";
|
|
||||||
|
|
||||||
Data.Set<IProgress>(new ProgressInfo()
|
|
||||||
{
|
|
||||||
Progress = 0.2f,
|
|
||||||
Message = message,
|
|
||||||
});
|
|
||||||
client.host = address;
|
|
||||||
client.port = port;
|
|
||||||
//client.ip=address;
|
|
||||||
//clientManager.port=port;
|
|
||||||
|
|
||||||
if (await client.Connect())
|
|
||||||
{
|
|
||||||
Data.Set<IProgress>(new ProgressInfo()
|
|
||||||
{
|
|
||||||
Progress = 0.1f,
|
|
||||||
Message = "已获取到在线服务器",
|
|
||||||
});
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
bool isConnected = false;
|
|
||||||
for (int i = 0; i < 3; i++)
|
|
||||||
{
|
|
||||||
if(await client.Connect())
|
|
||||||
{
|
|
||||||
isConnected=true;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
Data.Set<IProgress>(new ProgressInfo()
|
|
||||||
{
|
|
||||||
Progress = 0.1f + i*0.1f,
|
|
||||||
Message = "正在尝试重新连接到服务器",
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if(isConnected)
|
|
||||||
{
|
|
||||||
Data.Set<IProgress>(new ProgressInfo()
|
|
||||||
{
|
|
||||||
Progress = 0.5f,
|
|
||||||
Message = "已连接,正在加载中...",
|
|
||||||
});
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
Alert.Print(new()
|
|
||||||
{
|
|
||||||
title = "连接失败",
|
|
||||||
message = "已找到服务端但未找到服务器",
|
|
||||||
});
|
|
||||||
OnConnectFailed?.Invoke();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
catch (System.Net.Http.HttpRequestException e)
|
|
||||||
{
|
|
||||||
Alert.Print(new AlertMessage()
|
|
||||||
{
|
|
||||||
title = "未找到服务端:",
|
|
||||||
message = e.Message,
|
|
||||||
});
|
|
||||||
OnConnectFailed?.Invoke();
|
|
||||||
}
|
|
||||||
catch (System.Exception e)
|
|
||||||
{
|
|
||||||
Alert.Print(new AlertMessage()
|
|
||||||
{
|
|
||||||
title = "无法连接到服务端",
|
|
||||||
message = e.Message,
|
|
||||||
});
|
|
||||||
Debug.Log(e.GetType().FullName);
|
|
||||||
BIT4Log.LogException(e);
|
|
||||||
OnConnectFailed?.Invoke();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
void Awake()
|
|
||||||
{
|
|
||||||
Singleton = this;
|
|
||||||
DI.Register(this);
|
|
||||||
client = clientProvider.GetClient();
|
|
||||||
DI.Register(client);
|
|
||||||
|
|
||||||
}
|
|
||||||
void Start()
|
|
||||||
{
|
|
||||||
/*
|
|
||||||
* None,
|
|
||||||
Connected,
|
|
||||||
ConnectFailed,
|
|
||||||
TryToConnect,
|
|
||||||
TryToConnectFailed,
|
|
||||||
Disconnect,
|
|
||||||
ConnectLost,
|
|
||||||
ConnectClosed,
|
|
||||||
Connection,
|
|
||||||
Reconnect,
|
|
||||||
OnWhenQueuing,
|
|
||||||
OnQueueCancellation,
|
|
||||||
*/
|
|
||||||
client.AddStateHandler(NetworkState.Connected,OnConnected);
|
|
||||||
client.AddStateHandler(NetworkState.ConnectFailed,OnConnectFailed);
|
|
||||||
client.AddStateHandler(NetworkState.TryToConnect,OnTryToConnect);
|
|
||||||
client.AddStateHandler(NetworkState.TryToConnectFailed,OnTryToConnectFailed);
|
|
||||||
client.AddStateHandler(NetworkState.Disconnect,OnDisconnect);
|
|
||||||
client.AddStateHandler(NetworkState.ConnectLost,OnConnectLost);
|
|
||||||
client.AddStateHandler(NetworkState.ConnectClosed,OnConnectLost);
|
|
||||||
client.AddStateHandler(NetworkState.Connection,OnConnection);
|
|
||||||
client.AddStateHandler(NetworkState.Reconnect,OnReconnect);
|
|
||||||
client.AddStateHandler(NetworkState.OnWhenQueuing,OnOnWhenQueuing);
|
|
||||||
client.AddStateHandler(NetworkState.OnQueueCancellation,OnOnQueueCancellation);
|
|
||||||
}
|
|
||||||
|
|
||||||
void Update()
|
|
||||||
{
|
|
||||||
if (client is null || client.Client is null || client.Client.Connected is false) return;
|
|
||||||
while (Rpcs.TryDequeue(out var rpc))
|
|
||||||
{
|
|
||||||
client.SendRT(rpc.name,rpc.pars);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#if UNITY_EDITOR
|
|
||||||
[UnityEditor.CustomEditor(typeof(BITNet))]
|
|
||||||
public class BITNetInspector : BITInspector<BITNet>
|
|
||||||
{
|
|
||||||
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
}
|
|
|
@ -0,0 +1,13 @@
|
||||||
|
using System.Collections;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using Net.Client;
|
||||||
|
using UnityEngine;
|
||||||
|
|
||||||
|
namespace BITKit
|
||||||
|
{
|
||||||
|
public interface IGDNetClientProvider
|
||||||
|
{
|
||||||
|
ClientBase GetClient();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -1,7 +1,9 @@
|
||||||
using System;
|
using System;
|
||||||
using System.Collections;
|
using System.Collections;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
|
using System.Runtime.Remoting;
|
||||||
using Cysharp.Threading.Tasks;
|
using Cysharp.Threading.Tasks;
|
||||||
|
using JetBrains.Annotations;
|
||||||
using UnityEngine;
|
using UnityEngine;
|
||||||
using Net;
|
using Net;
|
||||||
using Net.Client;
|
using Net.Client;
|
||||||
|
@ -16,6 +18,7 @@ namespace BITKit
|
||||||
[Serializable]
|
[Serializable]
|
||||||
public class GDNetService:MonoBehaviour, INetProvider,INetClient
|
public class GDNetService:MonoBehaviour, INetProvider,INetClient
|
||||||
{
|
{
|
||||||
|
internal static GDNetService Singleton;
|
||||||
//服务器地址与端口号
|
//服务器地址与端口号
|
||||||
[Header(Constant.Header.Settings)]
|
[Header(Constant.Header.Settings)]
|
||||||
[SerializeField] private string address;
|
[SerializeField] private string address;
|
||||||
|
@ -23,7 +26,7 @@ namespace BITKit
|
||||||
[Header(Constant.Header.Components)]
|
[Header(Constant.Header.Components)]
|
||||||
//绑定GDNet的ClientManager
|
//绑定GDNet的ClientManager
|
||||||
[SerializeField,SerializeReference,SubclassSelector]
|
[SerializeField,SerializeReference,SubclassSelector]
|
||||||
private INetClientProvider clientProvider;
|
private IGDNetClientProvider clientProvider=null;
|
||||||
//内部事件系统
|
//内部事件系统
|
||||||
private readonly GenericEvent eventSystem = new();
|
private readonly GenericEvent eventSystem = new();
|
||||||
//内部变量
|
//内部变量
|
||||||
|
@ -32,14 +35,12 @@ namespace BITKit
|
||||||
private readonly List<object> rpcHandles = new();
|
private readonly List<object> rpcHandles = new();
|
||||||
//GDNet的网络客户端
|
//GDNet的网络客户端
|
||||||
private ClientBase client;
|
private ClientBase client;
|
||||||
/// <summary>
|
|
||||||
/// 是否已连接到服务端
|
|
||||||
/// </summary>
|
|
||||||
public bool IsConnected => client.Connected;
|
public bool IsConnected => client.Connected;
|
||||||
/// <summary>
|
|
||||||
/// 连接服务端的延迟
|
|
||||||
/// </summary>
|
|
||||||
public int Ping { get; private set; }
|
public int Ping { get; private set; }
|
||||||
|
|
||||||
|
public int Id => client.UID;
|
||||||
//客户端的基本回调
|
//客户端的基本回调
|
||||||
public event Action OnStartConnect;
|
public event Action OnStartConnect;
|
||||||
public event Action OnConnected;
|
public event Action OnConnected;
|
||||||
|
@ -48,9 +49,10 @@ namespace BITKit
|
||||||
|
|
||||||
public void ServerCommand<T>(T command=default)
|
public void ServerCommand<T>(T command=default)
|
||||||
{
|
{
|
||||||
SendRT("CallServerCommand",command);
|
//SendRT("OnServerCommand",command);
|
||||||
|
var bytes = BITBinary.WriteAsBytes(command);
|
||||||
|
client.Send(bytes);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void RpcClientCommand<T>(T command=default)
|
public void RpcClientCommand<T>(T command=default)
|
||||||
{
|
{
|
||||||
SendRT("CallRpcClientCommand",command);
|
SendRT("CallRpcClientCommand",command);
|
||||||
|
@ -88,7 +90,9 @@ namespace BITKit
|
||||||
|
|
||||||
public void SendRT(string rpcName, params object[] pars)
|
public void SendRT(string rpcName, params object[] pars)
|
||||||
{
|
{
|
||||||
client.SendRT(rpcName,pars);
|
// client.SendRT("Test",rpcName);
|
||||||
|
// client.SendRT(rpcName,pars);
|
||||||
|
// client.SendRT("TestMessage",rpcName);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void SendTargetRT(int id, string rpcName, params object[] pars)
|
public void SendTargetRT(int id, string rpcName, params object[] pars)
|
||||||
|
@ -110,12 +114,16 @@ namespace BITKit
|
||||||
{
|
{
|
||||||
client.AddRpcHandle(x);
|
client.AddRpcHandle(x);
|
||||||
}
|
}
|
||||||
|
client.AddRpcHandle(this);
|
||||||
OnStartConnect?.Invoke();
|
OnStartConnect?.Invoke();
|
||||||
if (await client.Connect())
|
if (await client.Connect())
|
||||||
{
|
{
|
||||||
OnConnected?.Invoke();
|
OnConnected?.Invoke();
|
||||||
}
|
}
|
||||||
OnConnectedFailed?.Invoke();
|
else
|
||||||
|
{
|
||||||
|
OnConnectedFailed?.Invoke();
|
||||||
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -130,10 +138,121 @@ namespace BITKit
|
||||||
eventSystem.Invoke($"{command.GetType().FullName}.{Constant.System.Internal}",command);
|
eventSystem.Invoke($"{command.GetType().FullName}.{Constant.System.Internal}",command);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void Awake()
|
||||||
|
{
|
||||||
|
Singleton = this;
|
||||||
|
}
|
||||||
private void Start()
|
private void Start()
|
||||||
{
|
{
|
||||||
client = clientProvider.GetClient();
|
client = clientProvider.GetClient();
|
||||||
|
client.AddRpcHandle(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Rpc]
|
||||||
|
private void OnClientCommand(object command)
|
||||||
|
{
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[Serializable]
|
||||||
|
public class GDNetServiceSingleton : INetClient,INetProvider
|
||||||
|
{
|
||||||
|
private INetProvider _netProviderImplementation => GDNetService.Singleton;
|
||||||
|
private INetClient _netClientImplementation => GDNetService.Singleton;
|
||||||
|
|
||||||
|
public event Action OnStartConnect
|
||||||
|
{
|
||||||
|
add => _netClientImplementation.OnStartConnect += value;
|
||||||
|
remove => _netClientImplementation.OnStartConnect -= value;
|
||||||
|
}
|
||||||
|
|
||||||
|
public event Action OnConnected
|
||||||
|
{
|
||||||
|
add => _netClientImplementation.OnConnected += value;
|
||||||
|
remove => _netClientImplementation.OnConnected -= value;
|
||||||
|
}
|
||||||
|
|
||||||
|
public event Action OnDisconnected
|
||||||
|
{
|
||||||
|
add => _netClientImplementation.OnDisconnected += value;
|
||||||
|
remove => _netClientImplementation.OnDisconnected -= value;
|
||||||
|
}
|
||||||
|
|
||||||
|
public event Action OnConnectedFailed
|
||||||
|
{
|
||||||
|
add => _netClientImplementation.OnConnectedFailed += value;
|
||||||
|
remove => _netClientImplementation.OnConnectedFailed -= value;
|
||||||
|
}
|
||||||
|
|
||||||
|
public UniTask<bool> Connect(string address = "localhost", ushort port = 27014)
|
||||||
|
{
|
||||||
|
return _netClientImplementation.Connect(address, port);
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool IsConnected => _netClientImplementation.IsConnected;
|
||||||
|
|
||||||
|
public int Ping => _netClientImplementation.Ping;
|
||||||
|
public int Id => _netClientImplementation.Id;
|
||||||
|
|
||||||
|
public void Disconnect()
|
||||||
|
{
|
||||||
|
_netClientImplementation.Disconnect();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void ServerCommand<T>(T command = default)
|
||||||
|
{
|
||||||
|
_netProviderImplementation.ServerCommand(command);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void RpcClientCommand<T>(T command = default)
|
||||||
|
{
|
||||||
|
_netProviderImplementation.RpcClientCommand(command);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void ClientCommand<T>(int id, T command)
|
||||||
|
{
|
||||||
|
_netProviderImplementation.ClientCommand(id, command);
|
||||||
|
}
|
||||||
|
|
||||||
|
public UniTask<T> GetFromServer<T>(string addressablePath = Constant.System.Internal)
|
||||||
|
{
|
||||||
|
return _netProviderImplementation.GetFromServer<T>(addressablePath);
|
||||||
|
}
|
||||||
|
|
||||||
|
public UniTask<T> GetFromClient<T>(int id, string addressablePath = Constant.System.Internal)
|
||||||
|
{
|
||||||
|
return _netProviderImplementation.GetFromClient<T>(id, addressablePath);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void AddRpcHandle(object rpcHandle)
|
||||||
|
{
|
||||||
|
_netProviderImplementation.AddRpcHandle(rpcHandle);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void AddCommandListener<T>(Action<T> handle)
|
||||||
|
{
|
||||||
|
_netProviderImplementation.AddCommandListener(handle);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void RemoveCommandListener<T>(Action<T> handle)
|
||||||
|
{
|
||||||
|
_netProviderImplementation.RemoveCommandListener(handle);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void SendRT(string rpcName, params object[] pars)
|
||||||
|
{
|
||||||
|
_netProviderImplementation.SendRT(rpcName, pars);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void SendTargetRT(int id, string rpcName, params object[] pars)
|
||||||
|
{
|
||||||
|
_netProviderImplementation.SendTargetRT(id, rpcName, pars);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void SendAllRT(string rpcName, params object[] pars)
|
||||||
|
{
|
||||||
|
_netProviderImplementation.SendAllRT(rpcName, pars);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -6,8 +6,9 @@ namespace BITKit.Steamwork
|
||||||
{
|
{
|
||||||
public interface ISteamService
|
public interface ISteamService
|
||||||
{
|
{
|
||||||
ulong GetSteamId { get; }
|
int Id { get; }
|
||||||
string GetName { get; }
|
ulong SteamId { get; }
|
||||||
|
string Name { get; }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -7,11 +7,18 @@ namespace BITKit.Steamwork
|
||||||
{
|
{
|
||||||
public class SteamService : MonoBehaviour,ISteamService
|
public class SteamService : MonoBehaviour,ISteamService
|
||||||
{
|
{
|
||||||
|
internal static SteamService Singleton;
|
||||||
[Header(Constant.Header.Settings)]
|
[Header(Constant.Header.Settings)]
|
||||||
[SerializeField]private uint appId=480;
|
[SerializeField]private uint appId=480;
|
||||||
//接口实现
|
//接口实现
|
||||||
public ulong GetSteamId => SteamClient.SteamId;
|
public ulong SteamId => SteamClient.SteamId;
|
||||||
public string GetName => SteamClient.Name;
|
public string Name => SteamClient.Name;
|
||||||
|
public int Id => (int)SteamClient.SteamId.AccountId;
|
||||||
|
|
||||||
|
private void Awake()
|
||||||
|
{
|
||||||
|
Singleton = this;
|
||||||
|
}
|
||||||
|
|
||||||
private void Start()
|
private void Start()
|
||||||
{
|
{
|
||||||
|
@ -33,5 +40,12 @@ namespace BITKit.Steamwork
|
||||||
SteamClient.Shutdown();
|
SteamClient.Shutdown();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
[Serializable]
|
||||||
|
public class SteamServiceSingleton:ISteamService
|
||||||
|
{
|
||||||
|
private ISteamService _steamServiceImplementation=>SteamService.Singleton;
|
||||||
|
public int Id => _steamServiceImplementation.Id;
|
||||||
|
public ulong SteamId => _steamServiceImplementation.SteamId;
|
||||||
|
public string Name => _steamServiceImplementation.Name;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -15,14 +15,6 @@ namespace BITKit
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
public class CreateOnStart:System.Attribute
|
|
||||||
{
|
|
||||||
public readonly string path;
|
|
||||||
public CreateOnStart(params string[] path)
|
|
||||||
{
|
|
||||||
this.path = string.Join("/", path);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
public class BITAppForUnity : MonoBehaviour, IDiagnostics
|
public class BITAppForUnity : MonoBehaviour, IDiagnostics
|
||||||
{
|
{
|
||||||
public struct Path
|
public struct Path
|
||||||
|
@ -55,43 +47,25 @@ namespace BITKit
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
[RuntimeInitializeOnLoadMethod]
|
[RuntimeInitializeOnLoadMethod]
|
||||||
private static async void Reload()
|
private static void Reload()
|
||||||
{
|
{
|
||||||
IsPlaying = true;
|
IsPlaying = true;
|
||||||
BIT4Log.OnLog += Debug.Log;
|
BIT4Log.OnLog += Debug.Log;
|
||||||
BIT4Log.OnWarning += Debug.LogWarning;
|
BIT4Log.OnWarning += Debug.LogWarning;
|
||||||
BIT4Log.OnException += Debug.LogException;
|
BIT4Log.OnException += Debug.LogException;
|
||||||
|
|
||||||
BIT4Log.Log<BITApp>($"正在初始化");
|
|
||||||
|
|
||||||
BIT4Log.Log<BITApp>($"正在注册Log");
|
|
||||||
|
|
||||||
BIT4Log.Log<BITApp>($"正在加载配置文件");
|
|
||||||
|
|
||||||
var settings = Addressables.LoadAssetAsync<ScriptableObject>(nameof(BITApp.AppSettings)).WaitForCompletion() as BITSettingsSO;
|
var settings = Addressables.LoadAssetAsync<ScriptableObject>(nameof(BITApp.AppSettings)).WaitForCompletion() as BITSettingsSO;
|
||||||
|
//启动BITApp
|
||||||
BIT4Log.Log<BITApp>($"正在启动{Application.productName}");
|
|
||||||
|
|
||||||
BITApp.Start(Application.productName, settings!.appSettings);
|
BITApp.Start(Application.productName, settings!.appSettings);
|
||||||
|
|
||||||
AllowCursor = new();
|
AllowCursor = new();
|
||||||
AllowTouchSupport = new();
|
AllowTouchSupport = new();
|
||||||
|
|
||||||
BIT4Log.Log<BITApp>($"正在创建{nameof(BITApp)}");
|
|
||||||
GameObject = new(nameof(BITApp));
|
GameObject = new(nameof(BITApp));
|
||||||
GameObject.AddComponent<BITAppForUnity>();
|
GameObject.AddComponent<BITAppForUnity>();
|
||||||
DontDestroyOnLoad(GameObject);
|
DontDestroyOnLoad(GameObject);
|
||||||
AllowCursor.AddListener(ToggleCursor);
|
AllowCursor.AddListener(ToggleCursor);
|
||||||
AllowTouchSupport.AddListener(ToggleTouchSupport);
|
AllowTouchSupport.AddListener(ToggleTouchSupport);
|
||||||
|
|
||||||
foreach (var x in await ReflectionHelper.GetAttributes<CreateOnStart>())
|
|
||||||
{
|
|
||||||
var prefab = Addressables.LoadAssetAsync<GameObject>(x.path).WaitForCompletion();
|
|
||||||
var instance = Instantiate(prefab);
|
|
||||||
DontDestroyOnLoad(instance);
|
|
||||||
}
|
|
||||||
|
|
||||||
BIT4Log.Log<BITApp>($"已创建{nameof(BITApp)}");
|
|
||||||
}
|
}
|
||||||
static void ToggleCursor(bool active)
|
static void ToggleCursor(bool active)
|
||||||
{
|
{
|
||||||
|
|
|
@ -1,13 +1,17 @@
|
||||||
using System.Collections;
|
using System.Collections;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using UnityEngine;
|
using UnityEngine;
|
||||||
|
using UnityEngine.AddressableAssets;
|
||||||
|
|
||||||
namespace BITKit
|
namespace BITKit
|
||||||
{
|
{
|
||||||
[CreateOnStart(BITAppForUnity.Path.Services,"Framework")]
|
|
||||||
public class BITFramework : MonoBehaviour
|
public class BITFramework : MonoBehaviour
|
||||||
{
|
{
|
||||||
|
[RuntimeInitializeOnLoadMethod]
|
||||||
|
private static void Reload()
|
||||||
|
{
|
||||||
|
Instantiate(Addressables.LoadAssetAsync<GameObject>("Services/Framework").WaitForCompletion());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -2,10 +2,10 @@ using System;
|
||||||
using System.Collections;
|
using System.Collections;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using UnityEngine;
|
using UnityEngine;
|
||||||
using Sirenix.OdinInspector;
|
|
||||||
using System.IO;
|
using System.IO;
|
||||||
using Cysharp.Threading.Tasks;
|
using Cysharp.Threading.Tasks;
|
||||||
using BITKit.IO;
|
using BITKit.IO;
|
||||||
|
using System.IO.Compression;
|
||||||
namespace BITKit
|
namespace BITKit
|
||||||
{
|
{
|
||||||
public class SaveToFile : Provider, IAction
|
public class SaveToFile : Provider, IAction
|
||||||
|
@ -63,7 +63,7 @@ namespace BITKit
|
||||||
string GetPath()
|
string GetPath()
|
||||||
{
|
{
|
||||||
string path;
|
string path;
|
||||||
var fileName = nameProvider.GetName(null, extensions);
|
var fileName = nameProvider.GetName(null, extensions.Get());
|
||||||
if (isPersistentData)
|
if (isPersistentData)
|
||||||
{
|
{
|
||||||
path = PathHelper.GetFilePath(Utility.Path.persistentDataPath, this.path.Get(), fileName);
|
path = PathHelper.GetFilePath(Utility.Path.persistentDataPath, this.path.Get(), fileName);
|
||||||
|
|
|
@ -57,7 +57,7 @@ namespace BITKit
|
||||||
private CinemachineBrain _brain;
|
private CinemachineBrain _brain;
|
||||||
public void Reset()
|
public void Reset()
|
||||||
{
|
{
|
||||||
lookInput = startLocation.position.TransientRotationAxis();
|
lookInput = MathV.TransientRotationAxis(startLocation.position);
|
||||||
cameraRoot.position = startLocation;
|
cameraRoot.position = startLocation;
|
||||||
tpv.CameraDistance = startDistance;
|
tpv.CameraDistance = startDistance;
|
||||||
}
|
}
|
||||||
|
@ -79,14 +79,14 @@ namespace BITKit
|
||||||
{
|
{
|
||||||
cameraRoot.position = x.cameraRoot.position;
|
cameraRoot.position = x.cameraRoot.position;
|
||||||
//lookInput = x.lookInput;
|
//lookInput = x.lookInput;
|
||||||
lookInput = x.cameraRoot.rotation.eulerAngles.TransientRotationAxis();
|
lookInput = MathV.TransientRotationAxis(x.cameraRoot.rotation.eulerAngles);
|
||||||
if (x.tpv)
|
if (x.tpv)
|
||||||
tpv.CameraDistance = x.tpv.CameraDistance;
|
tpv.CameraDistance = x.tpv.CameraDistance;
|
||||||
}
|
}
|
||||||
else if (target.TryGetComponent<CinemachineVirtualCamera>(out var vCam))
|
else if (target.TryGetComponent<CinemachineVirtualCamera>(out var vCam))
|
||||||
{
|
{
|
||||||
cameraRoot.position = vCam.Follow.position;
|
cameraRoot.position = vCam.Follow.position;
|
||||||
lookInput = vCam.LookAt.rotation.eulerAngles.TransientRotationAxis();
|
lookInput = MathV.TransientRotationAxis(vCam.LookAt.rotation.eulerAngles);
|
||||||
var e = vCam.GetCinemachineComponent<Cinemachine3rdPersonFollow>();
|
var e = vCam.GetCinemachineComponent<Cinemachine3rdPersonFollow>();
|
||||||
if (e)
|
if (e)
|
||||||
{
|
{
|
||||||
|
@ -97,7 +97,7 @@ namespace BITKit
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
cameraRoot.position = target.position;
|
cameraRoot.position = target.position;
|
||||||
lookInput = target.eulerAngles.TransientRotationAxis();
|
lookInput = MathV.TransientRotationAxis(target.eulerAngles);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
public void SaveLocation()
|
public void SaveLocation()
|
||||||
|
@ -115,7 +115,7 @@ namespace BITKit
|
||||||
}
|
}
|
||||||
public void LoadLocation()
|
public void LoadLocation()
|
||||||
{
|
{
|
||||||
lookInput = savedLocation.rotation.eulerAngles.TransientRotationAxis();
|
lookInput = MathV.TransientRotationAxis(savedLocation.rotation.eulerAngles);
|
||||||
cameraRoot.position = savedLocation;
|
cameraRoot.position = savedLocation;
|
||||||
tpv.CameraDistance = savedDistance;
|
tpv.CameraDistance = savedDistance;
|
||||||
}
|
}
|
||||||
|
@ -151,7 +151,7 @@ namespace BITKit
|
||||||
private void OnEnable()
|
private void OnEnable()
|
||||||
{
|
{
|
||||||
SetEnabled(true);
|
SetEnabled(true);
|
||||||
lookInput = cameraRoot.eulerAngles.TransientRotationAxis();
|
lookInput = MathV.TransientRotationAxis(cameraRoot.eulerAngles);
|
||||||
|
|
||||||
freeLooking.RemoveDisableElements(this);
|
freeLooking.RemoveDisableElements(this);
|
||||||
|
|
||||||
|
|
|
@ -32,8 +32,8 @@ namespace BITKit.Entities
|
||||||
if (id != value)
|
if (id != value)
|
||||||
{
|
{
|
||||||
id = value;
|
id = value;
|
||||||
EntitiesManager.Dictionary.TryRemove(id, out var _);
|
UnityEntitiesManager.Dictionary.TryRemove(id, out var _);
|
||||||
EntitiesManager.GetOrAdd(id, x => this);
|
UnityEntitiesManager.GetOrAdd(id, x => this);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -48,12 +48,12 @@ namespace BITKit.Entities
|
||||||
{
|
{
|
||||||
entityComponents.ForEach(x => x.OnAwake());
|
entityComponents.ForEach(x => x.OnAwake());
|
||||||
entityComponents.ForEach(x => x.OnStart());
|
entityComponents.ForEach(x => x.OnStart());
|
||||||
EntitiesManager.Dictionary.AddOrUpdate(id, (x) => this, (x1, x2) => this);
|
UnityEntitiesManager.Dictionary.AddOrUpdate(id, (x) => this, (x1, x2) => this);
|
||||||
}
|
}
|
||||||
protected virtual void OnDestroy()
|
protected virtual void OnDestroy()
|
||||||
{
|
{
|
||||||
entityComponents.ForEach(x => x.OnDestroyComponent());
|
entityComponents.ForEach(x => x.OnDestroyComponent());
|
||||||
EntitiesManager.Dictionary.TryRemove(id, out var _);
|
UnityEntitiesManager.Dictionary.TryRemove(id, out var _);
|
||||||
}
|
}
|
||||||
protected virtual void Update()
|
protected virtual void Update()
|
||||||
{
|
{
|
||||||
|
|
|
@ -21,7 +21,7 @@ namespace BITKit.Entities
|
||||||
{
|
{
|
||||||
var id = reader.ReadInt32();
|
var id = reader.ReadInt32();
|
||||||
var path = reader.ReadString();
|
var path = reader.ReadString();
|
||||||
var entity = EntitiesManager.GetOrAdd(id, _id => Create(id, path));
|
var entity = UnityEntitiesManager.GetOrAdd(id, _id => Create(id, path));
|
||||||
return entity;
|
return entity;
|
||||||
}
|
}
|
||||||
public override void WriteBinary(BinaryWriter writer, IEntity value)
|
public override void WriteBinary(BinaryWriter writer, IEntity value)
|
||||||
|
|
|
@ -5,17 +5,21 @@ using UnityEngine;
|
||||||
using UnityEngine.AddressableAssets;
|
using UnityEngine.AddressableAssets;
|
||||||
using BITKit;
|
using BITKit;
|
||||||
using System.Collections.Concurrent;
|
using System.Collections.Concurrent;
|
||||||
|
|
||||||
namespace BITKit.Entities
|
namespace BITKit.Entities
|
||||||
{
|
{
|
||||||
public class EntitiesManager
|
public interface IEntitesManager
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
public class UnityEntitiesManager:MonoBehaviour
|
||||||
{
|
{
|
||||||
[RuntimeInitializeOnLoadMethod]
|
[RuntimeInitializeOnLoadMethod]
|
||||||
static void Reload()
|
static void Reload()
|
||||||
{
|
{
|
||||||
Dictionary.Clear();
|
Dictionary.Clear();
|
||||||
}
|
}
|
||||||
public static ConcurrentDictionary<int, IEntity> Dictionary = new();
|
public static readonly ConcurrentDictionary<int, IEntity> Dictionary = new();
|
||||||
public static Func<int, IEntity> CreateFactory;
|
|
||||||
public static IEntity Get(int id)
|
public static IEntity Get(int id)
|
||||||
{
|
{
|
||||||
if (Dictionary.TryGetValue(id, out var entity))
|
if (Dictionary.TryGetValue(id, out var entity))
|
||||||
|
@ -29,8 +33,16 @@ namespace BITKit.Entities
|
||||||
}
|
}
|
||||||
public static IEntity GetOrAdd(int id)
|
public static IEntity GetOrAdd(int id)
|
||||||
{
|
{
|
||||||
return GetOrAdd(id, CreateFactory);
|
var instance = Instantiate(Singleton.prefab);
|
||||||
|
instance.Id = id;
|
||||||
|
return GetOrAdd(id,x=>instance);
|
||||||
}
|
}
|
||||||
public static IEntity GetOrAdd(int id, Func<int, IEntity> createFacotry) => Dictionary.GetOrAdd(id, createFacotry);
|
public static IEntity GetOrAdd(int id, Func<int, IEntity> createFacotry) => Dictionary.GetOrAdd(id, createFacotry);
|
||||||
|
private static UnityEntitiesManager Singleton;
|
||||||
|
public Entity prefab;
|
||||||
|
private void Awake()
|
||||||
|
{
|
||||||
|
Singleton = this;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -34,7 +34,7 @@ namespace BITKit.UX
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
await UniTask.SwitchToMainThread(gameObject.GetCancellationTokenOnDestroy());
|
await UniTask.SwitchToMainThread(cancellationToken);
|
||||||
switch (visualElement)
|
switch (visualElement)
|
||||||
{
|
{
|
||||||
case INotifyValueChanged<float> iNotify:
|
case INotifyValueChanged<float> iNotify:
|
||||||
|
@ -45,20 +45,23 @@ namespace BITKit.UX
|
||||||
fillElement.style.width = new StyleLength(Length.Percent(value));
|
fillElement.style.width = new StyleLength(Length.Percent(value));
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (labelElement is not null)
|
if (labelElement is not null)
|
||||||
labelElement.text = value.ToString();
|
labelElement.text = value.ToString();
|
||||||
}
|
}
|
||||||
catch (System.Exception e)
|
catch (OperationCanceledException)
|
||||||
{
|
{
|
||||||
if (e is not OperationCanceledException)
|
|
||||||
throw;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
public async void SetDirect(float progess,string label)
|
public async void SetDirect(float progess,string label)
|
||||||
{
|
{
|
||||||
await UniTask.SwitchToMainThread(gameObject.GetCancellationTokenOnDestroy());
|
await UniTask.SwitchToMainThread(cancellationToken);
|
||||||
Set(progess);
|
Set(progess);
|
||||||
labelElement.text = label;
|
if (labelElement is not null)
|
||||||
|
{
|
||||||
|
labelElement.text = label;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
float IProvider<float>.Get()
|
float IProvider<float>.Get()
|
||||||
{
|
{
|
||||||
|
|
|
@ -74,7 +74,7 @@ namespace BITKit
|
||||||
return direction.sqrMagnitude < factor; */
|
return direction.sqrMagnitude < factor; */
|
||||||
return Vector3.Angle(vectorX, vectorY) < 8;
|
return Vector3.Angle(vectorX, vectorY) < 8;
|
||||||
}
|
}
|
||||||
public static Vector3 TransientRotationAxis(this Vector3 transientAxis)
|
public static Vector3 TransientRotationAxis(Vector3 transientAxis)
|
||||||
{
|
{
|
||||||
transientAxis.x = TransientRotationAxis(transientAxis.x);
|
transientAxis.x = TransientRotationAxis(transientAxis.x);
|
||||||
transientAxis.y = TransientRotationAxis(transientAxis.y);
|
transientAxis.y = TransientRotationAxis(transientAxis.y);
|
||||||
|
@ -90,10 +90,10 @@ namespace BITKit
|
||||||
z = GetAlign(self.z),
|
z = GetAlign(self.z),
|
||||||
};
|
};
|
||||||
return result * snapSize;
|
return result * snapSize;
|
||||||
int GetAlign(float self)
|
int GetAlign(float _self)
|
||||||
{
|
{
|
||||||
var size = (int)self / snapSize;
|
var size = (int)_self / snapSize;
|
||||||
var remainder = self % snapSize;
|
var remainder = _self % snapSize;
|
||||||
return remainder > snapSize / 2 ? size + 1 : size;
|
return remainder > snapSize / 2 ? size + 1 : size;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -105,7 +105,7 @@ namespace BITKit
|
||||||
{
|
{
|
||||||
var addValue = self.x + self.y + self.z;
|
var addValue = self.x + self.y + self.z;
|
||||||
var subtractValue = self.x - self.y - self.z;
|
var subtractValue = self.x - self.y - self.z;
|
||||||
if (MathF.Abs(addValue) == Mathf.Abs(subtractValue))
|
if (Math.Abs(MathF.Abs(addValue) - Mathf.Abs(subtractValue)) < 0.01f)
|
||||||
{
|
{
|
||||||
return addValue;
|
return addValue;
|
||||||
}
|
}
|
||||||
|
|
|
@ -12,7 +12,6 @@ namespace BITKit
|
||||||
public string path;
|
public string path;
|
||||||
public Location location;
|
public Location location;
|
||||||
}
|
}
|
||||||
//[CreateOnStart(BITAppForUnity.Path.Services,nameof(VFXService))]
|
|
||||||
public class VFXService : MonoBehaviour, IObjectMatcher<string, Transform>
|
public class VFXService : MonoBehaviour, IObjectMatcher<string, Transform>
|
||||||
{
|
{
|
||||||
static VFXService sinleton;
|
static VFXService sinleton;
|
||||||
|
|
|
@ -21,21 +21,6 @@ MonoBehaviour:
|
||||||
m_Address: ItemSOEditor
|
m_Address: ItemSOEditor
|
||||||
m_ReadOnly: 0
|
m_ReadOnly: 0
|
||||||
m_SerializedLabels: []
|
m_SerializedLabels: []
|
||||||
- m_GUID: c11add6756d8d174bab79b05f24e618b
|
|
||||||
m_Address: Services/BulletService
|
|
||||||
m_ReadOnly: 0
|
|
||||||
m_SerializedLabels:
|
|
||||||
- Services
|
|
||||||
- m_GUID: 51d7444c7db67f042aa1d543f5609f87
|
|
||||||
m_Address: Services/BITNet
|
|
||||||
m_ReadOnly: 0
|
|
||||||
m_SerializedLabels:
|
|
||||||
- Services
|
|
||||||
- m_GUID: 9aabcf83d34f3794ab780926fe571c74
|
|
||||||
m_Address: Services/NetEntitesManager
|
|
||||||
m_ReadOnly: 0
|
|
||||||
m_SerializedLabels:
|
|
||||||
- Services
|
|
||||||
- m_GUID: f18510934c4581d47819abfbf1bd3647
|
- m_GUID: f18510934c4581d47819abfbf1bd3647
|
||||||
m_Address: Entity
|
m_Address: Entity
|
||||||
m_ReadOnly: 0
|
m_ReadOnly: 0
|
||||||
|
@ -68,16 +53,6 @@ MonoBehaviour:
|
||||||
m_Address: Clip_NATO
|
m_Address: Clip_NATO
|
||||||
m_ReadOnly: 0
|
m_ReadOnly: 0
|
||||||
m_SerializedLabels: []
|
m_SerializedLabels: []
|
||||||
- m_GUID: a14f3b822df215843adc179710c090a3
|
|
||||||
m_Address: Services/VFXService
|
|
||||||
m_ReadOnly: 0
|
|
||||||
m_SerializedLabels:
|
|
||||||
- Services
|
|
||||||
- m_GUID: 780b30340268e104b906eb20586769ee
|
|
||||||
m_Address: Services/UnityPlayerService
|
|
||||||
m_ReadOnly: 0
|
|
||||||
m_SerializedLabels:
|
|
||||||
- Services
|
|
||||||
- m_GUID: 374b2f92905c4f147abf889c9aeb5aab
|
- m_GUID: 374b2f92905c4f147abf889c9aeb5aab
|
||||||
m_Address: Services/Framework
|
m_Address: Services/Framework
|
||||||
m_ReadOnly: 0
|
m_ReadOnly: 0
|
||||||
|
|
|
@ -0,0 +1,69 @@
|
||||||
|
namespace Net.Component
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// 网络操作指令 (系统命令使用0-100, 基础网络组件使用100-150) 请从150开始自定义命令
|
||||||
|
/// </summary>
|
||||||
|
public class Command : Share.NetCmd
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// 客户端输入操作指令
|
||||||
|
/// </summary>
|
||||||
|
public const byte Input = 100;
|
||||||
|
/// <summary>
|
||||||
|
/// 玩家运动命令
|
||||||
|
/// </summary>
|
||||||
|
public const byte Movement = 101;
|
||||||
|
/// <summary>
|
||||||
|
/// 创建玩家命令
|
||||||
|
/// </summary>
|
||||||
|
public const byte CreatePlayer = 102;
|
||||||
|
/// <summary>
|
||||||
|
/// 玩家攻击命令
|
||||||
|
/// </summary>
|
||||||
|
public const byte Attack = 103;
|
||||||
|
/// <summary>
|
||||||
|
/// 同步生命值
|
||||||
|
/// </summary>
|
||||||
|
public const byte SyncHealth = 104;
|
||||||
|
/// <summary>
|
||||||
|
/// 玩家攻击到敌人
|
||||||
|
/// </summary>
|
||||||
|
public const byte Damage = 105;
|
||||||
|
/// <summary>
|
||||||
|
/// 敌人怪物AI同步指令
|
||||||
|
/// </summary>
|
||||||
|
public const byte EnemySync = 106;
|
||||||
|
/// <summary>
|
||||||
|
/// 玩家切换状态
|
||||||
|
/// </summary>
|
||||||
|
public const byte SwitchState = 107;
|
||||||
|
/// <summary>
|
||||||
|
/// 怪物切换状态
|
||||||
|
/// </summary>
|
||||||
|
public const byte EnemySwitchState = 108;
|
||||||
|
/// <summary>
|
||||||
|
/// Transform同步指令
|
||||||
|
/// <code><see cref="Net.Share.Operation.identity"/> 作为网络物体标识</code>
|
||||||
|
/// <code><see cref="Net.Share.Operation.index"/> 作为要实例化registerObjects的物体索引</code>
|
||||||
|
/// <code><see cref="Net.Share.Operation.index1"/> 用作NetComponentID区分</code>
|
||||||
|
/// <code><see cref="Net.Share.Operation.index2"/> 作为父子转换组件索引</code>
|
||||||
|
/// <code><see cref="Net.Share.Operation.cmd1"/> 作为SyncMode(同步模式)</code>
|
||||||
|
/// <code><see cref="Net.Share.Operation.position"/> 作为位置同步</code>
|
||||||
|
/// <code><see cref="Net.Share.Operation.rotation"/> 作为旋转同步</code>
|
||||||
|
/// <code><see cref="Net.Share.Operation.direction"/> 作为缩放同步</code>
|
||||||
|
/// </summary>
|
||||||
|
public const byte Transform = 109;
|
||||||
|
/// <summary>
|
||||||
|
/// NetworkIdentity组件被销毁指令
|
||||||
|
/// </summary>
|
||||||
|
public const byte Destroy = 110;
|
||||||
|
/// <summary>
|
||||||
|
/// 当客户端退出游戏, 通知其他客户端删除此客户端所生成的NetworkIdentity物体
|
||||||
|
/// </summary>
|
||||||
|
public const byte OnPlayerExit = 114;
|
||||||
|
/// <summary>
|
||||||
|
/// 网络组件生成工具同步指令
|
||||||
|
/// </summary>
|
||||||
|
public const byte BuildComponent = 115;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,163 @@
|
||||||
|
namespace Net.Component
|
||||||
|
{
|
||||||
|
using global::System;
|
||||||
|
using UnityEngine;
|
||||||
|
using Matrix4x4 = Matrix4x4;
|
||||||
|
using Quaternion = Quaternion;
|
||||||
|
using Vector3 = Vector3;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 游戏物体转换实体组建
|
||||||
|
/// 作者:彼岸流年 QQ:317392507
|
||||||
|
/// 后期修改:龙兄 QQ:1752062104
|
||||||
|
/// </summary>
|
||||||
|
[Serializable]
|
||||||
|
public class EntityTransform
|
||||||
|
{
|
||||||
|
public Matrix4x4 matrix;
|
||||||
|
|
||||||
|
public Vector3 position
|
||||||
|
{
|
||||||
|
get => matrix.GetPosition();
|
||||||
|
set => Matrix4Utils.SetPosition(ref matrix, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
public Quaternion rotation
|
||||||
|
{
|
||||||
|
get => matrix.GetRotation();
|
||||||
|
set => Matrix4Utils.Rotate(ref matrix, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
public UnityEngine.Vector3 localScale
|
||||||
|
{
|
||||||
|
get => matrix.GetScale();
|
||||||
|
}
|
||||||
|
|
||||||
|
public UnityEngine.Quaternion localRotation
|
||||||
|
{
|
||||||
|
get { return rotation; }
|
||||||
|
set { rotation = value; }
|
||||||
|
}
|
||||||
|
|
||||||
|
public Vector3 eulerAngles
|
||||||
|
{
|
||||||
|
get => rotation.eulerAngles;
|
||||||
|
set => rotation = Quaternion.Euler(value);
|
||||||
|
}
|
||||||
|
|
||||||
|
public Vector3 left
|
||||||
|
{
|
||||||
|
get => matrix.left;
|
||||||
|
set => matrix.left = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Vector3 right
|
||||||
|
{
|
||||||
|
get => matrix.right;
|
||||||
|
set => matrix.right = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Vector3 up
|
||||||
|
{
|
||||||
|
get => matrix.up;
|
||||||
|
set => matrix.up = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Vector3 down
|
||||||
|
{
|
||||||
|
get => matrix.down;
|
||||||
|
set => matrix.down = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Vector3 forward
|
||||||
|
{
|
||||||
|
get => matrix.forward;
|
||||||
|
set => matrix.forward = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Vector3 back
|
||||||
|
{
|
||||||
|
get => matrix.back;
|
||||||
|
set => matrix.back = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
public EntityTransform()
|
||||||
|
{
|
||||||
|
matrix = Matrix4Utils.GetPosition(Vector3.zero);
|
||||||
|
}
|
||||||
|
|
||||||
|
public EntityTransform(Vector3 position, Quaternion rotation)
|
||||||
|
{
|
||||||
|
Matrix4Utils.SetPosition(ref matrix, position);
|
||||||
|
Matrix4Utils.Rotate(ref matrix, rotation);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Translate(float x, float y, float z)
|
||||||
|
{
|
||||||
|
Translate(new Vector3(x, y, z));
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Translate(Vector3 direction)
|
||||||
|
{
|
||||||
|
Translate(direction, Space.Self);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Translate(Vector3 translation, Space relativeTo)
|
||||||
|
{
|
||||||
|
if (relativeTo == Space.World)
|
||||||
|
{
|
||||||
|
position += translation;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
matrix *= Matrix4x4.Translate(translation);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Rotate(Vector3 eulers, Space relativeTo)
|
||||||
|
{
|
||||||
|
var rhs = Quaternion.Euler(eulers.x, eulers.y, eulers.z);
|
||||||
|
if (relativeTo == Space.Self)
|
||||||
|
{
|
||||||
|
matrix *= Matrix4x4.Rotate(rhs);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
rotation *= Quaternion.Inverse(rotation) * rhs * rotation;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Rotate(Vector3 eulers)
|
||||||
|
{
|
||||||
|
Rotate(eulers, Space.Self);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Rotate(float xAngle, float yAngle, float zAngle, Space relativeTo)
|
||||||
|
{
|
||||||
|
Rotate(new Vector3(xAngle, yAngle, zAngle), relativeTo);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Rotate(float xAngle, float yAngle, float zAngle)
|
||||||
|
{
|
||||||
|
Rotate(new Vector3(xAngle, yAngle, zAngle), Space.Self);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void LookAt(Vector3 worldPosition)
|
||||||
|
{
|
||||||
|
LookAt(worldPosition, Vector3.up);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void LookAt(Vector3 worldPosition, Vector3 worldUp)
|
||||||
|
{
|
||||||
|
rotation = Quaternion.LookRotation(position, worldPosition, worldUp);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
[Serializable]
|
||||||
|
public class NTransform : EntityTransform
|
||||||
|
{
|
||||||
|
public NTransform() : base() { }
|
||||||
|
|
||||||
|
public NTransform(Vector3 position, Quaternion rotation) : base(position, rotation) { }
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,238 @@
|
||||||
|
using Net.Helper;
|
||||||
|
using Net.Share;
|
||||||
|
using System;
|
||||||
|
using System.Runtime.CompilerServices;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
|
namespace Net.Common
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// 属性观察接口
|
||||||
|
/// </summary>
|
||||||
|
/// <typeparam name="T"></typeparam>
|
||||||
|
public interface IPropertyObserver<T>
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// 属性值
|
||||||
|
/// </summary>
|
||||||
|
T Value { get; set; }
|
||||||
|
/// <summary>
|
||||||
|
/// 当属性被修改事件
|
||||||
|
/// </summary>
|
||||||
|
Action<T> OnValueChanged { get; set; }
|
||||||
|
/// <summary>
|
||||||
|
/// 获取属性值
|
||||||
|
/// </summary>
|
||||||
|
/// <returns></returns>
|
||||||
|
T GetValue();
|
||||||
|
/// <summary>
|
||||||
|
/// 设置属性值
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="value">新的属性值</param>
|
||||||
|
/// <param name="isNotify">是否通知事件</param>
|
||||||
|
void SetValue(T value, bool isNotify = true);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 属性观察类
|
||||||
|
/// </summary>
|
||||||
|
/// <typeparam name="T"></typeparam>
|
||||||
|
public class PropertyObserver<T> : IPropertyObserver<T>
|
||||||
|
{
|
||||||
|
protected T value;
|
||||||
|
public T Value { get => GetValue(); set => SetValue(value); }
|
||||||
|
public Action<T> OnValueChanged { get; set; }
|
||||||
|
public PropertyObserver() { }
|
||||||
|
public PropertyObserver(T value) : this(value, null) { }
|
||||||
|
public PropertyObserver(T value, Action<T> onValueChanged)
|
||||||
|
{
|
||||||
|
this.value = value;
|
||||||
|
OnValueChanged = onValueChanged;
|
||||||
|
}
|
||||||
|
|
||||||
|
public virtual T GetValue()
|
||||||
|
{
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
|
||||||
|
public virtual void SetValue(T value, bool isNotify = true)
|
||||||
|
{
|
||||||
|
if (Equals(this.value, value))
|
||||||
|
return;
|
||||||
|
this.value = value;
|
||||||
|
if (isNotify) OnValueChanged?.Invoke(value);
|
||||||
|
}
|
||||||
|
|
||||||
|
public override string ToString()
|
||||||
|
{
|
||||||
|
return $"{Value}";
|
||||||
|
}
|
||||||
|
|
||||||
|
public static implicit operator PropertyObserver<T>(T value)
|
||||||
|
{
|
||||||
|
return new PropertyObserver<T>(value, null);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static implicit operator T(PropertyObserver<T> value)
|
||||||
|
{
|
||||||
|
return value.Value;
|
||||||
|
}
|
||||||
|
|
||||||
|
public override bool Equals(object obj)
|
||||||
|
{
|
||||||
|
if (obj is PropertyObserver<T> value)
|
||||||
|
return Equals(value);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool Equals(PropertyObserver<T> obj)
|
||||||
|
{
|
||||||
|
return Value.Equals(obj.Value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 模糊属性观察类, 此类只支持byte, sbyte, short, ushort, char, int, uint, float, long, ulong, double
|
||||||
|
/// </summary>
|
||||||
|
/// <typeparam name="T"></typeparam>
|
||||||
|
public class ObscuredPropertyObserver<T> : IPropertyObserver<T>
|
||||||
|
{
|
||||||
|
private string name;
|
||||||
|
private long valueAtk;
|
||||||
|
private long valueAtkKey;
|
||||||
|
private byte crcValue;
|
||||||
|
public T Value { get => GetValue(); set => SetValue(value); }
|
||||||
|
public Action<T> OnValueChanged { get; set; }
|
||||||
|
|
||||||
|
public ObscuredPropertyObserver(T value) : this(null, value) { }
|
||||||
|
public ObscuredPropertyObserver(string name, T value) : this(name, value, null) { }
|
||||||
|
public ObscuredPropertyObserver(string name, T value, Action<T> onValueChanged)
|
||||||
|
{
|
||||||
|
this.name = name;
|
||||||
|
valueAtkKey = RandomHelper.Range(0, int.MaxValue);
|
||||||
|
SetValue(value);
|
||||||
|
OnValueChanged = onValueChanged;
|
||||||
|
}
|
||||||
|
|
||||||
|
public unsafe T GetValue()
|
||||||
|
{
|
||||||
|
var value = valueAtk ^ valueAtkKey;
|
||||||
|
var ptr = (byte*)&value;
|
||||||
|
var crcIndex = (byte)(valueAtk % 247);
|
||||||
|
crcValue = Net.Helper.CRCHelper.CRC8(ptr, 0, 8, crcIndex);
|
||||||
|
if (this.crcValue != crcValue)
|
||||||
|
{
|
||||||
|
AntiCheatHelper.OnDetected?.Invoke(name, value, value);
|
||||||
|
return default;
|
||||||
|
}
|
||||||
|
var value1 = Unsafe.As<long, T>(ref value);
|
||||||
|
return value1;
|
||||||
|
}
|
||||||
|
|
||||||
|
public unsafe void SetValue(T value, bool isNotify = true)
|
||||||
|
{
|
||||||
|
var value1 = Unsafe.As<T, long>(ref value);
|
||||||
|
valueAtk = value1 ^ valueAtkKey;
|
||||||
|
var ptr = (byte*)&value1;
|
||||||
|
var crcIndex = (byte)(valueAtk % 247);
|
||||||
|
crcValue = Net.Helper.CRCHelper.CRC8(ptr, 0, 8, crcIndex);
|
||||||
|
if (isNotify) OnValueChanged?.Invoke(value);
|
||||||
|
}
|
||||||
|
|
||||||
|
public override string ToString()
|
||||||
|
{
|
||||||
|
return $"{Value}";
|
||||||
|
}
|
||||||
|
|
||||||
|
public static implicit operator ObscuredPropertyObserver<T>(T value)
|
||||||
|
{
|
||||||
|
return new ObscuredPropertyObserver<T>(string.Empty, value, null);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static implicit operator T(ObscuredPropertyObserver<T> value)
|
||||||
|
{
|
||||||
|
return value.Value;
|
||||||
|
}
|
||||||
|
|
||||||
|
public override bool Equals(object obj)
|
||||||
|
{
|
||||||
|
if (obj is ObscuredPropertyObserver<T> value)
|
||||||
|
return Equals(value);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool Equals(ObscuredPropertyObserver<T> obj)
|
||||||
|
{
|
||||||
|
return Value.Equals(obj.Value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 属性观察自动类, 可模糊,不模糊
|
||||||
|
/// </summary>
|
||||||
|
/// <typeparam name="T"></typeparam>
|
||||||
|
public class PropertyObserverAuto<T> : IPropertyObserver<T>
|
||||||
|
{
|
||||||
|
private readonly bool available;
|
||||||
|
private IPropertyObserver<T> binding;
|
||||||
|
public T Value { get => GetValue(); set => SetValue(value); }
|
||||||
|
public Action<T> OnValueChanged { get => binding.OnValueChanged; set => binding.OnValueChanged = value; }
|
||||||
|
|
||||||
|
public PropertyObserverAuto() { }
|
||||||
|
/// <summary>
|
||||||
|
/// 属性观察自动类构造
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="name">当属性被发现修改时提示名称</param>
|
||||||
|
/// <param name="available">使用模糊属性?</param>
|
||||||
|
/// <param name="onValueChanged">当属性被修改事件</param>
|
||||||
|
public PropertyObserverAuto(string name, bool available, Action<T> onValueChanged) : this(name, available, default, onValueChanged)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
public PropertyObserverAuto(string name, bool available, T value, Action<T> onValueChanged)
|
||||||
|
{
|
||||||
|
this.available = available;
|
||||||
|
if (!AntiCheatHelper.IsActive | !available)
|
||||||
|
binding = new PropertyObserver<T>(value, onValueChanged);
|
||||||
|
else
|
||||||
|
binding = new ObscuredPropertyObserver<T>(name, value, onValueChanged);
|
||||||
|
}
|
||||||
|
|
||||||
|
public T GetValue()
|
||||||
|
{
|
||||||
|
return binding.GetValue();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void SetValue(T value, bool isNotify = true)
|
||||||
|
{
|
||||||
|
binding.SetValue(value, isNotify);
|
||||||
|
}
|
||||||
|
|
||||||
|
public override string ToString()
|
||||||
|
{
|
||||||
|
return $"{Value}";
|
||||||
|
}
|
||||||
|
|
||||||
|
public static implicit operator PropertyObserverAuto<T>(T value)
|
||||||
|
{
|
||||||
|
return new PropertyObserverAuto<T>(string.Empty, true, value, null);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static implicit operator T(PropertyObserverAuto<T> value)
|
||||||
|
{
|
||||||
|
return value.Value;
|
||||||
|
}
|
||||||
|
|
||||||
|
public override bool Equals(object obj)
|
||||||
|
{
|
||||||
|
if (obj is PropertyObserverAuto<T> value)
|
||||||
|
return Equals(value);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool Equals(PropertyObserverAuto<T> obj)
|
||||||
|
{
|
||||||
|
return Value.Equals(obj.Value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,39 @@
|
||||||
|
using Net.Share;
|
||||||
|
|
||||||
|
namespace Net.Component
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// 房间数据信息
|
||||||
|
/// </summary>
|
||||||
|
public class RoomData
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// 房间名称
|
||||||
|
/// </summary>
|
||||||
|
public string name;
|
||||||
|
/// <summary>
|
||||||
|
/// 房间可以组队人数
|
||||||
|
/// </summary>
|
||||||
|
public int num;
|
||||||
|
/// <summary>
|
||||||
|
/// 当前加入房间人数
|
||||||
|
/// </summary>
|
||||||
|
public int currNum;
|
||||||
|
/// <summary>
|
||||||
|
/// 房间的状态
|
||||||
|
/// </summary>
|
||||||
|
public NetState state;
|
||||||
|
/// <summary>
|
||||||
|
/// 竞技模式 1:个人 2:团队
|
||||||
|
/// </summary>
|
||||||
|
public int mode;
|
||||||
|
}
|
||||||
|
|
||||||
|
public class JoinData
|
||||||
|
{
|
||||||
|
public string name;//玩家名称
|
||||||
|
public bool ready;//是否准备
|
||||||
|
public bool teamTag;//true:为红队 false:为绿队
|
||||||
|
public string iconName;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,64 @@
|
||||||
|
#if UNITY_STANDALONE || UNITY_ANDROID || UNITY_IOS || UNITY_WSA || UNITY_WEBGL
|
||||||
|
namespace Net.Component
|
||||||
|
{
|
||||||
|
using UnityEngine;
|
||||||
|
|
||||||
|
public class ARPGcamera : MonoBehaviour
|
||||||
|
{
|
||||||
|
public Transform target;
|
||||||
|
public float targetHeight = 1.2f;
|
||||||
|
public float distance = 4.0f;
|
||||||
|
public float maxDistance = 20;
|
||||||
|
public float minDistance = 1.0f;
|
||||||
|
public float xSpeed = 500.0f;
|
||||||
|
public float ySpeed = 120.0f;
|
||||||
|
public float yMinLimit = -10;
|
||||||
|
public float yMaxLimit = 70;
|
||||||
|
public float zoomRate = 80;
|
||||||
|
public float rotationDampening = 3.0f;
|
||||||
|
public float x = 20.0f;
|
||||||
|
public float y = 0.0f;
|
||||||
|
public float aimAngle = 8;
|
||||||
|
public KeyCode key = KeyCode.Mouse1;
|
||||||
|
protected Quaternion aim;
|
||||||
|
protected Quaternion rotation;
|
||||||
|
private Vector3 position;
|
||||||
|
|
||||||
|
void LateUpdate()
|
||||||
|
{
|
||||||
|
if (!target)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (Input.GetKey(key) | key == KeyCode.None)
|
||||||
|
{
|
||||||
|
x += Input.GetAxis("Mouse X") * xSpeed * 0.02f;
|
||||||
|
y -= Input.GetAxis("Mouse Y") * ySpeed * 0.02f;
|
||||||
|
}
|
||||||
|
|
||||||
|
distance -= Input.GetAxis("Mouse ScrollWheel") * Time.deltaTime * zoomRate * Mathf.Abs(distance);
|
||||||
|
distance = Mathf.Clamp(distance, minDistance, maxDistance);
|
||||||
|
|
||||||
|
y = ClampAngle(y, yMinLimit, yMaxLimit);
|
||||||
|
|
||||||
|
// Rotate Camera
|
||||||
|
rotation = Quaternion.Euler(y, x, 0);
|
||||||
|
transform.rotation = rotation;
|
||||||
|
|
||||||
|
aim = Quaternion.Euler(y - aimAngle, x, 0);
|
||||||
|
|
||||||
|
//Camera Position
|
||||||
|
position = target.position - (rotation * Vector3.forward * distance + new Vector3(0, -targetHeight, 0));
|
||||||
|
transform.position = position;
|
||||||
|
}
|
||||||
|
|
||||||
|
static float ClampAngle(float angle, float min, float max)
|
||||||
|
{
|
||||||
|
if (angle < -360)
|
||||||
|
angle += 360;
|
||||||
|
if (angle > 360)
|
||||||
|
angle -= 360;
|
||||||
|
return Mathf.Clamp(angle, min, max);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
|
@ -0,0 +1,22 @@
|
||||||
|
#if UNITY_STANDALONE || UNITY_ANDROID || UNITY_IOS || UNITY_WSA || UNITY_WEBGL
|
||||||
|
using UnityEngine;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 只显示不能修改的属性
|
||||||
|
/// </summary>
|
||||||
|
public class DisplayOnly : PropertyAttribute
|
||||||
|
{
|
||||||
|
public string text;
|
||||||
|
public DisplayOnly() { }
|
||||||
|
public DisplayOnly(string text)
|
||||||
|
{
|
||||||
|
this.text = text;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
///<summary>
|
||||||
|
///定义多选属性
|
||||||
|
///</summary>
|
||||||
|
public class EnumFlags : PropertyAttribute { }
|
||||||
|
|
||||||
|
#endif
|
|
@ -0,0 +1,124 @@
|
||||||
|
#if UNITY_STANDALONE || UNITY_ANDROID || UNITY_IOS || UNITY_WSA || UNITY_WEBGL
|
||||||
|
namespace Net.UnityComponent
|
||||||
|
{
|
||||||
|
using global::System;
|
||||||
|
using Net.Share;
|
||||||
|
using UnityEngine;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 网络行为基础组件
|
||||||
|
/// </summary>
|
||||||
|
[DefaultExecutionOrder(1000)]
|
||||||
|
public abstract class NetworkBehaviour : MonoBehaviour
|
||||||
|
{
|
||||||
|
public NetworkObject netObj;
|
||||||
|
[Tooltip("网络组件的ID,当FPS游戏时,自己身上只有一双手和枪,而其他客户端要显示完整模型时,用到另外的预制体,就会出现组件获取不一致问题,所以这里提供了网络组件ID,即可解决此问题")]
|
||||||
|
[SerializeField] private int netComponentID = -1;
|
||||||
|
/// <summary>
|
||||||
|
/// 网络组件id, 此组件是netobj的第几个组件
|
||||||
|
/// </summary>
|
||||||
|
public int NetComponentID
|
||||||
|
{
|
||||||
|
get { return netComponentID > 10 ? -1 : netComponentID; }
|
||||||
|
set
|
||||||
|
{
|
||||||
|
if (value > 10)
|
||||||
|
throw new Exception("组件最多不能超过10个");
|
||||||
|
netComponentID = value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/// <summary>
|
||||||
|
/// 这个物体是本机生成的?
|
||||||
|
/// true:这个物体是从你本机实例化后, 同步给其他客户端的, 其他客户端的IsLocal为false
|
||||||
|
/// false:这个物体是其他客户端实例化后,同步到本机客户端上, IsLocal为false
|
||||||
|
/// </summary>
|
||||||
|
public bool IsLocal => netObj.isLocal;
|
||||||
|
private bool isInit;
|
||||||
|
private bool isEnabled;
|
||||||
|
public virtual void Start()
|
||||||
|
{
|
||||||
|
Init();
|
||||||
|
}
|
||||||
|
private void OnValidate()
|
||||||
|
{
|
||||||
|
if (TryGetComponent(out netObj))
|
||||||
|
return;
|
||||||
|
netObj = gameObject.GetComponentInParent<NetworkObject>(true); //此处需要加上参数true, 否则做成预制体时会找不到父组件
|
||||||
|
if (netObj == null)
|
||||||
|
netObj = gameObject.AddComponent<NetworkObject>();
|
||||||
|
}
|
||||||
|
public void Init(Operation opt = default)
|
||||||
|
{
|
||||||
|
if (isInit)
|
||||||
|
return;
|
||||||
|
isInit = true;
|
||||||
|
netObj = GetComponentInParent<NetworkObject>();
|
||||||
|
if (NetComponentID == -1)
|
||||||
|
{
|
||||||
|
NetComponentID = netObj.networkBehaviours.Count;
|
||||||
|
netObj.networkBehaviours.Add(this);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
while (netObj.networkBehaviours.Count <= NetComponentID)
|
||||||
|
netObj.networkBehaviours.Add(null);
|
||||||
|
if (netObj.networkBehaviours[NetComponentID] != null)
|
||||||
|
throw new Exception($"索引有冲突!打开预制体设置{this}组件的NetComponentID值为唯一ID!");
|
||||||
|
netObj.networkBehaviours[NetComponentID] = this;
|
||||||
|
}
|
||||||
|
netObj.InitSyncVar(this);
|
||||||
|
if (IsLocal)
|
||||||
|
OnNetworkObjectInit(netObj.Identity);
|
||||||
|
else
|
||||||
|
OnNetworkObjectCreate(opt);
|
||||||
|
}
|
||||||
|
/// <summary>
|
||||||
|
/// 当网络物体被初始化, 只有本机实例化的物体才会被调用
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="identity"></param>
|
||||||
|
public virtual void OnNetworkObjectInit(int identity) { }
|
||||||
|
/// <summary>
|
||||||
|
/// 当网络物体被创建后调用, 只有其他客户端发送创建信息给本机后才会被调用
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="opt"></param>
|
||||||
|
public virtual void OnNetworkObjectCreate(Operation opt) { }
|
||||||
|
/// <summary>
|
||||||
|
/// 当网络操作到达后应当开发者进行处理
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="opt"></param>
|
||||||
|
public virtual void OnNetworkOperationHandler(Operation opt) { }
|
||||||
|
/// <summary>
|
||||||
|
/// 当属性自动同步检查
|
||||||
|
/// </summary>
|
||||||
|
public virtual void OnPropertyAutoCheck() { }
|
||||||
|
/// <summary>
|
||||||
|
/// 检查组件是否启用
|
||||||
|
/// </summary>
|
||||||
|
/// <returns></returns>
|
||||||
|
public virtual bool CheckEnabled() { return isEnabled; }
|
||||||
|
public virtual void OnEnable()
|
||||||
|
{
|
||||||
|
isEnabled = true;
|
||||||
|
}
|
||||||
|
public virtual void OnDisable()
|
||||||
|
{
|
||||||
|
isEnabled = false;
|
||||||
|
}
|
||||||
|
public virtual void OnDestroy()
|
||||||
|
{
|
||||||
|
netObj.RemoveSyncVar(this);
|
||||||
|
var nbs = netObj.networkBehaviours;
|
||||||
|
for (int i = 0; i < nbs.Count; i++)
|
||||||
|
{
|
||||||
|
var nb = nbs[i];
|
||||||
|
nb.NetComponentID = i;
|
||||||
|
if (nb == this)
|
||||||
|
{
|
||||||
|
nbs.RemoveAt(i);
|
||||||
|
if (i >= 0) i--;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
|
@ -0,0 +1,299 @@
|
||||||
|
#if UNITY_STANDALONE || UNITY_ANDROID || UNITY_IOS || UNITY_WSA || UNITY_WEBGL
|
||||||
|
using Net.Client;
|
||||||
|
using Net.Event;
|
||||||
|
using Net.Share;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using UnityEngine;
|
||||||
|
using System.Net;
|
||||||
|
using System;
|
||||||
|
using Net.Helper;
|
||||||
|
using Cysharp.Threading.Tasks;
|
||||||
|
|
||||||
|
namespace Net.Component
|
||||||
|
{
|
||||||
|
[Serializable]
|
||||||
|
public class ClientGourp
|
||||||
|
{
|
||||||
|
public string name;
|
||||||
|
public ClientBase _client;
|
||||||
|
public TransportProtocol protocol = TransportProtocol.Tcp;
|
||||||
|
public string ip = "127.0.0.1";
|
||||||
|
public int port = 9543;
|
||||||
|
#if UNITY_EDITOR
|
||||||
|
public bool localTest;//本机测试
|
||||||
|
#endif
|
||||||
|
public bool debugRpc = true;
|
||||||
|
public bool authorize;
|
||||||
|
public bool startConnect = true;
|
||||||
|
public bool md5CRC;
|
||||||
|
public bool singleThread;
|
||||||
|
public int reconnectCount = 10;
|
||||||
|
public int reconnectInterval = 2000;
|
||||||
|
public byte heartLimit = 5;
|
||||||
|
public int heartInterval = 1000;
|
||||||
|
[Header("序列化适配器")]
|
||||||
|
public SerializeAdapterType type;
|
||||||
|
public bool isEncrypt = false;//数据加密?
|
||||||
|
public int password = 758426581;
|
||||||
|
|
||||||
|
public ClientBase Client
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
if (_client != null)
|
||||||
|
return _client;
|
||||||
|
var typeName = $"Net.Client.{protocol}Client";
|
||||||
|
var type = AssemblyHelper.GetType(typeName);
|
||||||
|
if (type == null)
|
||||||
|
throw new Exception($"请导入:{protocol}协议!!!");
|
||||||
|
_client = Activator.CreateInstance(type, new object[] { true }) as ClientBase;
|
||||||
|
_client.host = ip;
|
||||||
|
_client.port = port;
|
||||||
|
_client.LogRpc = debugRpc;
|
||||||
|
_client.MD5CRC = md5CRC;
|
||||||
|
_client.IsMultiThread = !singleThread;
|
||||||
|
_client.ReconnectCount = reconnectCount;
|
||||||
|
_client.ReconnectInterval = reconnectInterval;
|
||||||
|
_client.SetHeartTime(heartLimit, heartInterval);
|
||||||
|
return _client;
|
||||||
|
}
|
||||||
|
set { _client = value; }
|
||||||
|
}
|
||||||
|
|
||||||
|
public UniTask<bool> Connect()
|
||||||
|
{
|
||||||
|
_client = Client;
|
||||||
|
var ips = Dns.GetHostAddresses(ip);
|
||||||
|
if (ips.Length > 0)
|
||||||
|
_client.host = ips[RandomHelper.Range(0, ips.Length)].ToString();
|
||||||
|
else
|
||||||
|
_client.host = ip;
|
||||||
|
#if UNITY_EDITOR
|
||||||
|
if (localTest) _client.host = "127.0.0.1";
|
||||||
|
#endif
|
||||||
|
_client.port = port;
|
||||||
|
switch (type)
|
||||||
|
{
|
||||||
|
case SerializeAdapterType.Default:
|
||||||
|
break;
|
||||||
|
case SerializeAdapterType.PB_JSON_FAST:
|
||||||
|
_client.AddAdapter(new Adapter.SerializeFastAdapter() { IsEncrypt = isEncrypt, Password = password });
|
||||||
|
break;
|
||||||
|
case SerializeAdapterType.Binary:
|
||||||
|
_client.AddAdapter(new Adapter.SerializeAdapter() { IsEncrypt = isEncrypt, Password = password });
|
||||||
|
break;
|
||||||
|
case SerializeAdapterType.Binary2:
|
||||||
|
_client.AddAdapter(new Adapter.SerializeAdapter2() { IsEncrypt = isEncrypt, Password = password });
|
||||||
|
break;
|
||||||
|
case SerializeAdapterType.Binary3:
|
||||||
|
_client.AddAdapter(new Adapter.SerializeAdapter3() { IsEncrypt = isEncrypt, Password = password });
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
return _client.Connect(result =>
|
||||||
|
{
|
||||||
|
if (result)
|
||||||
|
{
|
||||||
|
_client.Send(new byte[1]);//发送一个字节:调用服务器的OnUnClientRequest方法, 如果不需要账号登录, 则会直接允许进入服务器
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
public UniTask<bool> Connect(string ip, int port)
|
||||||
|
{
|
||||||
|
this.ip = ip;
|
||||||
|
this.port = port;
|
||||||
|
return Connect();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public class NetworkManager : SingleCase<NetworkManager>
|
||||||
|
{
|
||||||
|
public LogMode logMode = LogMode.Default;
|
||||||
|
public bool dontDestroyOnLoad = true;
|
||||||
|
#if UNITY_2020_1_OR_NEWER
|
||||||
|
[NonReorderable]
|
||||||
|
#endif
|
||||||
|
public List<ClientGourp> clients = new List<ClientGourp>();
|
||||||
|
|
||||||
|
public ClientBase this[int index]
|
||||||
|
{
|
||||||
|
get { return clients[index].Client; }
|
||||||
|
set { clients[index].Client = value; }
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override void Awake()
|
||||||
|
{
|
||||||
|
base.Awake();
|
||||||
|
if (dontDestroyOnLoad) DontDestroyOnLoad(gameObject);
|
||||||
|
Application.runInBackground = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Use this for initialization
|
||||||
|
void Start()
|
||||||
|
{
|
||||||
|
switch (logMode)
|
||||||
|
{
|
||||||
|
case LogMode.Default:
|
||||||
|
NDebug.BindLogAll(Debug.Log, Debug.LogWarning, Debug.LogError);
|
||||||
|
break;
|
||||||
|
case LogMode.LogAll:
|
||||||
|
NDebug.BindLogAll(Debug.Log);
|
||||||
|
break;
|
||||||
|
case LogMode.LogAndWarning:
|
||||||
|
NDebug.BindLogAll(Debug.Log, Debug.Log, Debug.LogError);
|
||||||
|
break;
|
||||||
|
case LogMode.WarnAndError:
|
||||||
|
NDebug.BindLogAll(Debug.Log, Debug.LogError, Debug.LogError);
|
||||||
|
break;
|
||||||
|
case LogMode.OnlyError:
|
||||||
|
NDebug.BindLogAll(null, null, Debug.LogError);
|
||||||
|
break;
|
||||||
|
case LogMode.OnlyWarnAndError:
|
||||||
|
NDebug.BindLogAll(null, Debug.LogError, Debug.LogError);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
foreach (var client in clients)
|
||||||
|
{
|
||||||
|
if (client.startConnect)
|
||||||
|
client.Connect();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Update is called once per frame
|
||||||
|
void Update()
|
||||||
|
{
|
||||||
|
for (int i = 0; i < clients.Count; i++)
|
||||||
|
{
|
||||||
|
if (clients[i]._client == null)
|
||||||
|
continue;
|
||||||
|
clients[i]._client.NetworkTick();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void OnDestroy()
|
||||||
|
{
|
||||||
|
for (int i = 0; i < clients.Count; i++)
|
||||||
|
{
|
||||||
|
if (clients[i]._client == null)
|
||||||
|
continue;
|
||||||
|
clients[i]._client.Close();
|
||||||
|
}
|
||||||
|
switch (logMode)
|
||||||
|
{
|
||||||
|
case LogMode.Default:
|
||||||
|
NDebug.RemoveLogAll(Debug.Log, Debug.LogWarning, Debug.LogError);
|
||||||
|
break;
|
||||||
|
case LogMode.LogAll:
|
||||||
|
NDebug.RemoveLogAll(Debug.Log);
|
||||||
|
break;
|
||||||
|
case LogMode.LogAndWarning:
|
||||||
|
NDebug.RemoveLogAll(Debug.Log, Debug.Log, Debug.LogError);
|
||||||
|
break;
|
||||||
|
case LogMode.WarnAndError:
|
||||||
|
NDebug.RemoveLogAll(Debug.Log, Debug.LogError, Debug.LogError);
|
||||||
|
break;
|
||||||
|
case LogMode.OnlyError:
|
||||||
|
NDebug.RemoveLogAll(null, null, Debug.LogError);
|
||||||
|
break;
|
||||||
|
case LogMode.OnlyWarnAndError:
|
||||||
|
NDebug.RemoveLogAll(null, Debug.LogError, Debug.LogError);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void BindNetworkAll(INetworkHandle handle)
|
||||||
|
{
|
||||||
|
foreach (var item in I.clients)
|
||||||
|
{
|
||||||
|
item.Client.BindNetworkHandle(handle);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 添加索引0的客户端rpc, 也就是1的客户端
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="target"></param>
|
||||||
|
public static void AddRpcOne(object target)
|
||||||
|
{
|
||||||
|
I.clients[0].Client.AddRpc(target);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 添加索引1的客户端, 也就是2的客户端
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="target"></param>
|
||||||
|
public static void AddRpcTwo(object target)
|
||||||
|
{
|
||||||
|
I.clients[1].Client.AddRpc(target);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 添加指定索引的客户端rpc, 如果索引小于0则为全部添加
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="clientIndex"></param>
|
||||||
|
/// <param name="target"></param>
|
||||||
|
public static void AddRpc(int clientIndex, object target)
|
||||||
|
{
|
||||||
|
if (clientIndex < 0)
|
||||||
|
foreach (var item in I.clients)
|
||||||
|
item.Client.AddRpc(target);
|
||||||
|
else I.clients[clientIndex].Client.AddRpc(target);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 移除索引0的客户端rpc, 也就是1的客户端
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="target"></param>
|
||||||
|
public static void RemoveRpcOne(object target)
|
||||||
|
{
|
||||||
|
I.clients[0].Client.RemoveRpc(target);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 移除索引1的客户端rpc, 也就是2的客户端
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="target"></param>
|
||||||
|
public static void RemoveRpcTwo(object target)
|
||||||
|
{
|
||||||
|
var i = Instance;
|
||||||
|
if (i == null)
|
||||||
|
return;
|
||||||
|
i.clients[1].Client.RemoveRpc(target);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 移除指定索引的客户端rpc, 如果索引小于0则为全部添加
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="clientIndex"></param>
|
||||||
|
/// <param name="target"></param>
|
||||||
|
public static void RemoveRpc(int clientIndex, object target)
|
||||||
|
{
|
||||||
|
var i = Instance;
|
||||||
|
if (i == null)
|
||||||
|
return;
|
||||||
|
if (clientIndex < 0)
|
||||||
|
foreach (var item in i.clients)
|
||||||
|
item.Client.RemoveRpc(target);
|
||||||
|
else i.clients[clientIndex].Client.RemoveRpc(target);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void Close(bool v1, int v2)
|
||||||
|
{
|
||||||
|
foreach (var item in I.clients)
|
||||||
|
{
|
||||||
|
item.Client.Close(v1, v2);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void CallUnity(Action ptr)
|
||||||
|
{
|
||||||
|
I.clients[0].Client.WorkerQueue.Enqueue(ptr);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void DispatcherRpc(ushort hash, params object[] parms)
|
||||||
|
{
|
||||||
|
I.clients[1].Client.DispatchRpc(hash, parms);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
|
@ -0,0 +1,269 @@
|
||||||
|
#if UNITY_STANDALONE || UNITY_ANDROID || UNITY_IOS || UNITY_WSA || UNITY_WEBGL
|
||||||
|
namespace Net.UnityComponent
|
||||||
|
{
|
||||||
|
using global::System.Collections.Generic;
|
||||||
|
using Net.Client;
|
||||||
|
using Net.Component;
|
||||||
|
using Net.Helper;
|
||||||
|
using Net.Share;
|
||||||
|
using Net.System;
|
||||||
|
using UnityEngine;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 网络物体标识组件
|
||||||
|
/// </summary>
|
||||||
|
[DisallowMultipleComponent]
|
||||||
|
[DefaultExecutionOrder(1000)]
|
||||||
|
public class NetworkObject : MonoBehaviour
|
||||||
|
{
|
||||||
|
internal static int IDENTITY { get; private set; } = -1;
|
||||||
|
internal static int IDENTITY_MAX { get; private set; }
|
||||||
|
internal static Queue<int> IDENTITY_POOL = new Queue<int>();
|
||||||
|
public static int Capacity { get; private set; }
|
||||||
|
public static bool IsInitIdentity => IDENTITY != -1;
|
||||||
|
private int m_identity = -1;
|
||||||
|
[Tooltip("自定义唯一标识, 当值不为0后,可以不通过NetworkSceneManager的registerObjects去设置, 直接放在设计的场景里面, 不需要做成预制体")]
|
||||||
|
[SerializeField] private int identity;//可以设置的id
|
||||||
|
[Tooltip("注册的网络物体索引, registerObjectIndex要对应NetworkSceneManager的registerObjects数组索引, 如果设置了自定义唯一标识, 则此字段无效!")]
|
||||||
|
public int registerObjectIndex;
|
||||||
|
[SerializeField] internal bool isLocal = true;
|
||||||
|
internal List<NetworkBehaviour> networkBehaviours = new List<NetworkBehaviour>();
|
||||||
|
internal MyDictionary<ushort, SyncVarInfo> syncVarInfos = new MyDictionary<ushort, SyncVarInfo>();
|
||||||
|
private int syncVarID = 1;
|
||||||
|
[Tooltip("是否初始化? 如果不想让Identity在Start被自动分配ID, 则可以设置此字段为true")]
|
||||||
|
[SerializeField] internal bool isInit;
|
||||||
|
public bool IsDispose { get; internal set; }
|
||||||
|
/// <summary>
|
||||||
|
/// 此物体是否是本机实例化?
|
||||||
|
/// </summary>
|
||||||
|
public bool IsLocal { get => isLocal; set => isLocal = value; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 每个网络对象的唯一标识
|
||||||
|
/// </summary>
|
||||||
|
public int Identity { get => m_identity; set => m_identity = value; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 获取或设置是否初始化
|
||||||
|
/// </summary>
|
||||||
|
public bool IsInitialize { get => isInit; set => isInit = value; }
|
||||||
|
|
||||||
|
public virtual void Start()
|
||||||
|
{
|
||||||
|
Init();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void ReInit()
|
||||||
|
{
|
||||||
|
isInit = false;
|
||||||
|
Init();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Init()
|
||||||
|
{
|
||||||
|
if (isInit)
|
||||||
|
return;
|
||||||
|
isInit = true;
|
||||||
|
if (IDENTITY == -1 & identity == 0)//全局netobj
|
||||||
|
{
|
||||||
|
Debug.LogError("网络标识未初始化,请调用NetworkObject.Init(5000);初始化");
|
||||||
|
Destroy(gameObject);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
var sm = NetworkSceneManager.I;
|
||||||
|
if (sm == null)
|
||||||
|
{
|
||||||
|
Debug.Log("没有找到NetworkSceneManager组件!NetworkIdentity组件无效!");
|
||||||
|
Destroy(gameObject);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (!isLocal | m_identity > 0)
|
||||||
|
{
|
||||||
|
goto J1;
|
||||||
|
}
|
||||||
|
if (identity > 0)
|
||||||
|
{
|
||||||
|
m_identity = identity;
|
||||||
|
goto J1;
|
||||||
|
}
|
||||||
|
if (IDENTITY_POOL.Count > 0)
|
||||||
|
{
|
||||||
|
m_identity = IDENTITY_POOL.Dequeue();
|
||||||
|
goto J1;
|
||||||
|
}
|
||||||
|
if (IDENTITY < IDENTITY_MAX)
|
||||||
|
{
|
||||||
|
m_identity = IDENTITY++;
|
||||||
|
goto J1;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Debug.LogError("网络标识已用完! 如果有需要请加大网络标识数量NetworkObject.Init(10000);");
|
||||||
|
Destroy(gameObject);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
J1:
|
||||||
|
if (!sm.identitys.TryAdd(m_identity, this, out var oldNetObj))
|
||||||
|
{
|
||||||
|
if (oldNetObj == this | oldNetObj == null)
|
||||||
|
return;
|
||||||
|
oldNetObj.m_identity = -1;
|
||||||
|
Debug.Log($"uid:{m_identity}发生了两次实例化! 本地的实例化和网络同步下来的identity冲突");
|
||||||
|
Destroy(oldNetObj.gameObject);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void InitAll(Operation opt = default)
|
||||||
|
{
|
||||||
|
Init();
|
||||||
|
var nbs = GetComponentsInChildren<NetworkBehaviour>();
|
||||||
|
foreach (var np in nbs)
|
||||||
|
{
|
||||||
|
np.Init(opt);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
internal void InitSyncVar(object target)
|
||||||
|
{
|
||||||
|
ClientBase.Instance.AddRpcHandle(target, false, (info) =>
|
||||||
|
{
|
||||||
|
info.id = (ushort)syncVarID++;
|
||||||
|
syncVarInfos.Add(info.id, info);
|
||||||
|
if (!isLocal)
|
||||||
|
{
|
||||||
|
ClientBase.Instance.AddOperation(new Operation(NetCmd.SyncVarGet, m_identity)
|
||||||
|
{
|
||||||
|
index = registerObjectIndex,
|
||||||
|
index1 = info.id,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
internal void CheckSyncVar()
|
||||||
|
{
|
||||||
|
if (syncVarInfos.Count == 0)
|
||||||
|
return;
|
||||||
|
var buffer = SyncVarHelper.CheckSyncVar(isLocal, syncVarInfos);
|
||||||
|
if (buffer != null)
|
||||||
|
SyncVarSend(buffer);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void SyncVarSend(byte[] buffer)
|
||||||
|
{
|
||||||
|
ClientBase.Instance.AddOperation(new Operation(NetCmd.SyncVarNetObj, m_identity)
|
||||||
|
{
|
||||||
|
uid = ClientBase.Instance.UID,
|
||||||
|
index = registerObjectIndex,
|
||||||
|
buffer = buffer
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
internal void SyncVarHandler(Operation opt)
|
||||||
|
{
|
||||||
|
if (opt.uid == ClientBase.Instance.UID)
|
||||||
|
return;
|
||||||
|
SyncVarHelper.SyncVarHandler(syncVarInfos, opt.buffer);
|
||||||
|
}
|
||||||
|
|
||||||
|
internal void RemoveSyncVar(NetworkBehaviour target)
|
||||||
|
{
|
||||||
|
SyncVarHelper.RemoveSyncVar(syncVarInfos, target);
|
||||||
|
}
|
||||||
|
|
||||||
|
internal void PropertyAutoCheckHandler()
|
||||||
|
{
|
||||||
|
for (int i = 0; i < networkBehaviours.Count; i++)
|
||||||
|
{
|
||||||
|
var networkBehaviour = networkBehaviours[i];
|
||||||
|
if (!networkBehaviour.CheckEnabled())
|
||||||
|
continue;
|
||||||
|
networkBehaviour.OnPropertyAutoCheck();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public virtual void OnDestroy()
|
||||||
|
{
|
||||||
|
if (IsDispose)
|
||||||
|
return;
|
||||||
|
IsDispose = true;
|
||||||
|
if (m_identity == -1)
|
||||||
|
return;
|
||||||
|
var sm = NetworkSceneManager.Instance;
|
||||||
|
if (sm == null)
|
||||||
|
return;
|
||||||
|
if (!isLocal | m_identity < 10000)//0-10000是场景可用标识
|
||||||
|
{
|
||||||
|
sm.waitDestroyList.Add(new WaitDestroy(m_identity, false, Time.time + 1f));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
sm.waitDestroyList.Add(new WaitDestroy(m_identity, true, Time.time + 1f));
|
||||||
|
if (ClientBase.Instance == null)
|
||||||
|
return;
|
||||||
|
if (!ClientBase.Instance.Connected)
|
||||||
|
return;
|
||||||
|
ClientBase.Instance.AddOperation(new Operation(Command.Destroy, m_identity));
|
||||||
|
}
|
||||||
|
|
||||||
|
internal static void PushIdentity(int identity)
|
||||||
|
{
|
||||||
|
if (IDENTITY == -1)
|
||||||
|
return;
|
||||||
|
IDENTITY_POOL.Enqueue(identity);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 初始化网络唯一标识
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="capacity">一个客户端可以用的唯一标识容量</param>
|
||||||
|
public static void Init(int capacity = 5000)
|
||||||
|
{
|
||||||
|
//要实时可初始化,要不然每次切换场景都无法初始化id,或者切换账号后uid变了,就得不到真正的identity值了
|
||||||
|
Capacity = capacity;
|
||||||
|
//0-10000是公共id,10000-15000是玩家uid,也就是同时在线5000个玩家,每个玩家占用一个id,15000-20000是uid=10000的网络物体id,
|
||||||
|
//每个玩家可以实例化5000个网络物体,并且id都是唯一的,如果超出则报错
|
||||||
|
IDENTITY = 10000 + ((ClientBase.Instance.UID + 1 - 10000) * capacity);
|
||||||
|
IDENTITY_MAX = IDENTITY + capacity;
|
||||||
|
IDENTITY_POOL.Clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 释放初始化的identity
|
||||||
|
/// </summary>
|
||||||
|
public static void UnInit()
|
||||||
|
{
|
||||||
|
IDENTITY = -1;
|
||||||
|
IDENTITY_MAX = 0;
|
||||||
|
Capacity = 0;
|
||||||
|
IDENTITY_POOL.Clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 获取玩家id的偏移量, 此方法算出来每个玩家可实例化多少个网络对象
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="uid"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
public static int GetUserIdOffset(int uid)
|
||||||
|
{
|
||||||
|
//0-10000是公共id,10000-15000是玩家uid,也就是同时在线5000个玩家,每个玩家占用一个id,15000-20000是uid=10000的网络物体id,
|
||||||
|
//每个玩家可以实例化5000个网络物体,并且id都是唯一的,如果超出则报错
|
||||||
|
return 10000 + ((uid + 1 - 10000) * Capacity);
|
||||||
|
}
|
||||||
|
|
||||||
|
#if UNITY_EDITOR
|
||||||
|
private void OnValidate()
|
||||||
|
{
|
||||||
|
var networkBehaviours = gameObject.GetComponentsInChildren<NetworkBehaviour>(true);
|
||||||
|
for (int i = 0; i < networkBehaviours.Length; i++)
|
||||||
|
{
|
||||||
|
var networkBehaviour = networkBehaviours[i];
|
||||||
|
if (networkBehaviour.NetComponentID == -1)
|
||||||
|
{
|
||||||
|
networkBehaviour.NetComponentID = i;
|
||||||
|
UnityEditor.EditorUtility.SetDirty(networkBehaviour);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
|
@ -0,0 +1,75 @@
|
||||||
|
#if UNITY_STANDALONE || UNITY_ANDROID || UNITY_IOS || UNITY_WSA || UNITY_WEBGL
|
||||||
|
using System;
|
||||||
|
using UnityEngine;
|
||||||
|
using Net.Component;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using Object = UnityEngine.Object;
|
||||||
|
|
||||||
|
namespace Net.UnityComponent
|
||||||
|
{
|
||||||
|
[Serializable]
|
||||||
|
public class ObjectRecord
|
||||||
|
{
|
||||||
|
public int ID;
|
||||||
|
public Object obj;
|
||||||
|
public string path;//编辑器模式使用,任何物体都可以同步
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 网络资源同步
|
||||||
|
/// 此类主要用于同步字段为unity的组件或者基于UnityEngine.Objec的类型
|
||||||
|
/// 在编辑器模式下是任何物体都可以同步的, 注意: 在编译项目后, 只能同步在Resources文件夹下的预制体或物体
|
||||||
|
/// </summary>
|
||||||
|
public class NetworkResources : SingleCase<NetworkResources>
|
||||||
|
{
|
||||||
|
public ObjectRecord[] objectRecords;
|
||||||
|
public Dictionary<Object, ObjectRecord> dic = new Dictionary<Object, ObjectRecord>();
|
||||||
|
public Dictionary<string, ObjectRecord> dic1 = new Dictionary<string, ObjectRecord>();
|
||||||
|
|
||||||
|
protected override void Awake()
|
||||||
|
{
|
||||||
|
base.Awake();
|
||||||
|
var objects = Resources.LoadAll<Object>("");
|
||||||
|
objectRecords = new ObjectRecord[objects.Length];
|
||||||
|
for (int i = 0; i < objects.Length; i++)
|
||||||
|
{
|
||||||
|
objectRecords[i] = new ObjectRecord() { ID = i, obj = objects[i] };
|
||||||
|
dic.Add(objects[i], objectRecords[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
internal bool TryGetValue(Object obj, out ObjectRecord objectRecord)
|
||||||
|
{
|
||||||
|
#if UNITY_EDITOR
|
||||||
|
if (!dic.TryGetValue(obj, out objectRecord))
|
||||||
|
{
|
||||||
|
var path = UnityEditor.AssetDatabase.GetAssetPath(obj);
|
||||||
|
objectRecord = new ObjectRecord() { ID = dic.Count, obj = obj, path = path };
|
||||||
|
dic.Add(obj, objectRecord);
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
#else
|
||||||
|
return dic.TryGetValue(obj, out objectRecord);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
internal T GetObject<T>(int index, string path) where T : Object
|
||||||
|
{
|
||||||
|
#if UNITY_EDITOR
|
||||||
|
if(string.IsNullOrEmpty(path))
|
||||||
|
return null;
|
||||||
|
if (!dic1.TryGetValue(path, out ObjectRecord objectRecord))
|
||||||
|
{
|
||||||
|
var obj = UnityEditor.AssetDatabase.LoadAssetAtPath(path, typeof(T));
|
||||||
|
objectRecord = new ObjectRecord() { ID = dic1.Count, obj = obj, path = path };
|
||||||
|
dic1.Add(path, objectRecord);
|
||||||
|
}
|
||||||
|
return (T)objectRecord.obj;
|
||||||
|
#else
|
||||||
|
return (T)objectRecords[index].obj;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
|
@ -0,0 +1,323 @@
|
||||||
|
#if UNITY_STANDALONE || UNITY_ANDROID || UNITY_IOS || UNITY_WSA || UNITY_WEBGL
|
||||||
|
namespace Net.UnityComponent
|
||||||
|
{
|
||||||
|
using global::System;
|
||||||
|
using global::System.Collections.Generic;
|
||||||
|
using Net.Client;
|
||||||
|
using Net.Component;
|
||||||
|
using Net.Share;
|
||||||
|
using Net.System;
|
||||||
|
using UnityEngine;
|
||||||
|
using Cysharp.Threading.Tasks;
|
||||||
|
|
||||||
|
[Serializable]
|
||||||
|
public class WaitDestroy
|
||||||
|
{
|
||||||
|
public int identity;
|
||||||
|
public bool isPush;
|
||||||
|
public float time;
|
||||||
|
|
||||||
|
public WaitDestroy(int identity, bool isPush, float time)
|
||||||
|
{
|
||||||
|
this.identity = identity;
|
||||||
|
this.isPush = isPush;
|
||||||
|
this.time = time;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
[DefaultExecutionOrder(1)]
|
||||||
|
public class NetworkSceneManager : SingleCase<NetworkSceneManager>
|
||||||
|
{
|
||||||
|
public List<NetworkObject> registerObjects = new List<NetworkObject>();
|
||||||
|
[HideInInspector]
|
||||||
|
public MyDictionary<int, NetworkObject> identitys = new MyDictionary<int, NetworkObject>();
|
||||||
|
[Tooltip("如果onExitDelectAll=true 当客户端退出游戏,客户端所创建的所有网络物体也将随之被删除? onExitDelectAll=false只删除玩家物体")]
|
||||||
|
public bool onExitDelectAll = true;
|
||||||
|
internal List<WaitDestroy> waitDestroyList = new List<WaitDestroy>();
|
||||||
|
protected ClientBase client; //当多场景时, 退出战斗场景, 回主场景时, 先进入主场景再卸载战斗场景, 而ClientBase.Instance被赋值到其他多连接客户端对象上就会出现OnDestry时没有正确移除OnOperationSync事件
|
||||||
|
protected Queue<Action> waitNetworkIdentityQueue = new Queue<Action>();
|
||||||
|
|
||||||
|
public virtual void Start()
|
||||||
|
{
|
||||||
|
_ = WaitConnecting();
|
||||||
|
if (NetworkTime.Instance == null)
|
||||||
|
gameObject.AddComponent<NetworkTime>();
|
||||||
|
}
|
||||||
|
|
||||||
|
public virtual async UniTaskVoid WaitConnecting()
|
||||||
|
{
|
||||||
|
var outTime = DateTime.Now.AddSeconds(10);
|
||||||
|
while (DateTime.Now < outTime)
|
||||||
|
{
|
||||||
|
if (ClientBase.Instance == null)
|
||||||
|
await UniTask.Yield();
|
||||||
|
else if (!ClientBase.Instance.Connected)
|
||||||
|
await UniTask.Yield();
|
||||||
|
else
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (DateTime.Now > outTime)
|
||||||
|
{
|
||||||
|
Debug.Log("连接超时!");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
OnConnected();
|
||||||
|
client = ClientBase.Instance;
|
||||||
|
client.OnOperationSync += OperationSync;
|
||||||
|
while (waitNetworkIdentityQueue.Count > 0)
|
||||||
|
waitNetworkIdentityQueue.Dequeue()?.Invoke();
|
||||||
|
}
|
||||||
|
|
||||||
|
public virtual void OnConnected()
|
||||||
|
{
|
||||||
|
NetworkObject.Init(5000);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 等待网络标识初始化, 当标识初始化完成调用onInitComplete委托
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="onInitComplete"></param>
|
||||||
|
public virtual void WaitNetworkIdentityInit(Action onInitComplete)
|
||||||
|
{
|
||||||
|
if (NetworkObject.IsInitIdentity)
|
||||||
|
onInitComplete?.Invoke();
|
||||||
|
else
|
||||||
|
waitNetworkIdentityQueue.Enqueue(onInitComplete);
|
||||||
|
}
|
||||||
|
|
||||||
|
public virtual void Update()
|
||||||
|
{
|
||||||
|
if (NetworkTime.CanSent)
|
||||||
|
{
|
||||||
|
for (int i = 0; i < identitys.count; i++)
|
||||||
|
{
|
||||||
|
if (identitys.entries[i].hashCode == -1)
|
||||||
|
continue;
|
||||||
|
var identity = identitys.entries[i].value;
|
||||||
|
if (identity == null)
|
||||||
|
continue;
|
||||||
|
if (!identity.enabled)
|
||||||
|
continue;
|
||||||
|
if (identity.IsDispose)
|
||||||
|
continue;
|
||||||
|
identity.CheckSyncVar();
|
||||||
|
identity.PropertyAutoCheckHandler();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
WaitDestroy waitDestroy;
|
||||||
|
for (int i = 0; i < waitDestroyList.Count; i++)
|
||||||
|
{
|
||||||
|
waitDestroy = waitDestroyList[i];
|
||||||
|
if (Time.time >= waitDestroy.time)
|
||||||
|
{
|
||||||
|
RemoveIdentity(waitDestroy.identity);
|
||||||
|
waitDestroyList.RemoveAt(i);
|
||||||
|
if (!waitDestroy.isPush)
|
||||||
|
continue;
|
||||||
|
NetworkObject.PushIdentity(waitDestroy.identity);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void OperationSync(OperationList list)
|
||||||
|
{
|
||||||
|
foreach (var opt in list.operations)
|
||||||
|
OnNetworkOperSync(opt);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void OnNetworkOperSync(Operation opt)
|
||||||
|
{
|
||||||
|
switch (opt.cmd)
|
||||||
|
{
|
||||||
|
case Command.Transform:
|
||||||
|
OnBuildOrTransformSync(opt);
|
||||||
|
break;
|
||||||
|
case Command.BuildComponent:
|
||||||
|
OnBuildOrTransformSync(opt);
|
||||||
|
break;
|
||||||
|
case Command.Destroy:
|
||||||
|
OnNetworkObjectDestroy(opt);
|
||||||
|
break;
|
||||||
|
case Command.OnPlayerExit:
|
||||||
|
OnPlayerExit(opt);
|
||||||
|
break;
|
||||||
|
case NetCmd.SyncVarNetObj:
|
||||||
|
OnSyncVarHandler(opt);
|
||||||
|
break;
|
||||||
|
case NetCmd.SyncVarGet:
|
||||||
|
SyncVarGetHandler(opt);
|
||||||
|
break;
|
||||||
|
case NetCmd.CallRpc:
|
||||||
|
var data = client.OnDeserializeRPC(opt.buffer, 0, opt.buffer.Length);
|
||||||
|
if(!string.IsNullOrEmpty(data.name))
|
||||||
|
client.DispatchRpc(data.name, data.pars);
|
||||||
|
else if(data.hash != 0)
|
||||||
|
client.DispatchRpc(data.hash, data.pars);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
OnOtherOperator(opt);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 当检查网络标识物体,如果不存在就会实例化 --- 在这里用到了<see cref="Operation.identity"/>作为网络物体标识, <see cref="Operation.index"/>作为要实例化<see cref="registerObjects"/>的物体索引
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="opt"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
public virtual NetworkObject OnCheckIdentity(Operation opt)
|
||||||
|
{
|
||||||
|
if (!identitys.TryGetValue(opt.identity, out NetworkObject identity))
|
||||||
|
{
|
||||||
|
if (opt.index >= registerObjects.Count)
|
||||||
|
return null;
|
||||||
|
identity = Instantiate(registerObjects[opt.index]);
|
||||||
|
identity.Identity = opt.identity;
|
||||||
|
identity.isLocal = false;
|
||||||
|
identity.isInit = true;
|
||||||
|
identity.InitAll(opt);
|
||||||
|
identitys.TryAdd(opt.identity, identity);
|
||||||
|
OnNetworkObjectCreate(opt, identity);
|
||||||
|
}
|
||||||
|
return identity;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 当BuildComponent指令或Transform指令同步时调用
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="opt"></param>
|
||||||
|
public virtual void OnBuildOrTransformSync(Operation opt)
|
||||||
|
{
|
||||||
|
var identity = OnCheckIdentity(opt);
|
||||||
|
if (identity == null)
|
||||||
|
return;
|
||||||
|
if (identity.IsDispose)
|
||||||
|
return;
|
||||||
|
var nb = identity.networkBehaviours[opt.index1];
|
||||||
|
nb.OnNetworkOperationHandler(opt);
|
||||||
|
}
|
||||||
|
|
||||||
|
public virtual void OnSyncVarHandler(Operation opt)
|
||||||
|
{
|
||||||
|
var identity = OnCheckIdentity(opt);
|
||||||
|
if (identity == null)
|
||||||
|
return;
|
||||||
|
if (identity.IsDispose)
|
||||||
|
return;
|
||||||
|
identity.SyncVarHandler(opt);
|
||||||
|
}
|
||||||
|
|
||||||
|
public virtual void SyncVarGetHandler(Operation opt)
|
||||||
|
{
|
||||||
|
var identity = OnCheckIdentity(opt);
|
||||||
|
if (identity == null)
|
||||||
|
return;
|
||||||
|
if (identity.IsDispose)
|
||||||
|
return;
|
||||||
|
if (!identity.isLocal)
|
||||||
|
return;
|
||||||
|
identity.syncVarInfos[(ushort)opt.index1].SetDefaultValue();
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 当其他网络物体被删除(入口1)
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="opt"></param>
|
||||||
|
public virtual void OnNetworkObjectDestroy(Operation opt)
|
||||||
|
{
|
||||||
|
if (identitys.TryGetValue(opt.identity, out NetworkObject identity))
|
||||||
|
{
|
||||||
|
OnPlayerDestroy(identity, false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public virtual void OnPlayerExit(Operation opt)
|
||||||
|
{
|
||||||
|
if (identitys.TryGetValue(opt.identity, out NetworkObject identity))//删除退出游戏的玩家游戏物体
|
||||||
|
OnPlayerDestroy(identity, true);
|
||||||
|
if (onExitDelectAll)//删除此玩家所创建的所有游戏物体
|
||||||
|
{
|
||||||
|
var uid = NetworkObject.GetUserIdOffset(opt.identity);
|
||||||
|
var count = uid + NetworkObject.Capacity;
|
||||||
|
foreach (var item in identitys)
|
||||||
|
if (item.Key >= uid & item.Key < count)
|
||||||
|
OnPlayerDestroy(item.Value, false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void OnPlayerDestroy(NetworkObject identity, bool isPlayer)
|
||||||
|
{
|
||||||
|
if (identity == null)
|
||||||
|
return;
|
||||||
|
if (identity.IsDispose)
|
||||||
|
return;
|
||||||
|
if(isPlayer)
|
||||||
|
OnOtherExit(identity);
|
||||||
|
OnOtherDestroy(identity);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void RemoveIdentity(int identity)
|
||||||
|
{
|
||||||
|
identitys.Remove(identity);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 当其他网络物体被创建(实例化)
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="opt"></param>
|
||||||
|
/// <param name="identity"></param>
|
||||||
|
public virtual void OnNetworkObjectCreate(Operation opt, NetworkObject identity)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 当其他网络物体被删除(入口2)
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="identity"></param>
|
||||||
|
public virtual void OnOtherDestroy(NetworkObject identity)
|
||||||
|
{
|
||||||
|
Destroy(identity.gameObject);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 当其他玩家网络物体退出(删除)
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="identity"></param>
|
||||||
|
public virtual void OnOtherExit(NetworkObject identity)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 当其他操作指令调用
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="opt"></param>
|
||||||
|
public virtual void OnOtherOperator(Operation opt)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
private void OnApplicationQuit()
|
||||||
|
{
|
||||||
|
ExitSceneHandler();
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 当退出场景时有些网络物体是不应该被销毁的
|
||||||
|
/// </summary>
|
||||||
|
public void ExitSceneHandler()
|
||||||
|
{
|
||||||
|
foreach (var identity in identitys)
|
||||||
|
{
|
||||||
|
identity.Value.Identity = -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public virtual void OnDestroy()
|
||||||
|
{
|
||||||
|
NetworkObject.UnInit();//每次离开战斗场景都要清除初始化identity
|
||||||
|
if (client == null)
|
||||||
|
return;
|
||||||
|
client.OnOperationSync -= OperationSync;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
|
@ -0,0 +1,14 @@
|
||||||
|
#if UNITY_STANDALONE || UNITY_ANDROID || UNITY_IOS || UNITY_WSA || UNITY_WEBGL
|
||||||
|
using UnityEngine;
|
||||||
|
|
||||||
|
namespace Net.UnityComponent
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// 网络Transform同步组件基类
|
||||||
|
/// </summary>
|
||||||
|
[DefaultExecutionOrder(1000)]
|
||||||
|
public class NetworkTransform : NetworkTransformBase
|
||||||
|
{
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
|
@ -0,0 +1,202 @@
|
||||||
|
#if UNITY_STANDALONE || UNITY_ANDROID || UNITY_IOS || UNITY_WSA || UNITY_WEBGL
|
||||||
|
namespace Net.UnityComponent
|
||||||
|
{
|
||||||
|
using Net.Client;
|
||||||
|
using Net.Component;
|
||||||
|
using Net.Share;
|
||||||
|
using UnityEngine;
|
||||||
|
using UnityEngine.UIElements;
|
||||||
|
|
||||||
|
public enum SyncMode
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// 自身同步, 只有自身才能控制, 同步给其他客户端, 其他客户端无法控制这个物体的移动
|
||||||
|
/// </summary>
|
||||||
|
Local,
|
||||||
|
/// <summary>
|
||||||
|
/// 完全控制, 所有客户端都可以移动这个物体, 并且其他客户端都会被同步
|
||||||
|
/// 同步条件是哪个先移动这个物体会有<see cref="NetworkTransformBase.interval"/>秒完全控制,
|
||||||
|
/// 其他客户端无法控制,如果先移动的客户端一直移动这个物体,则其他客户端无法移动,只有先移动的客户端停止操作,下个客户端才能同步这个物体
|
||||||
|
/// </summary>
|
||||||
|
Control,
|
||||||
|
/// <summary>
|
||||||
|
/// 无效
|
||||||
|
/// </summary>
|
||||||
|
Authorize,
|
||||||
|
/// <summary>
|
||||||
|
/// 自身同步在其他客户端显示的状态
|
||||||
|
/// </summary>
|
||||||
|
Synchronized,
|
||||||
|
/// <summary>
|
||||||
|
/// 完全控制在其他客户端显示的状态
|
||||||
|
/// </summary>
|
||||||
|
SynchronizedAll,
|
||||||
|
/// <summary>
|
||||||
|
/// 空同步
|
||||||
|
/// </summary>
|
||||||
|
None,
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 网络Transform同步组件基类
|
||||||
|
/// </summary>
|
||||||
|
[DefaultExecutionOrder(1000)]
|
||||||
|
public abstract class NetworkTransformBase : NetworkBehaviour
|
||||||
|
{
|
||||||
|
protected Net.Vector3 position;
|
||||||
|
protected Net.Quaternion rotation;
|
||||||
|
protected Net.Vector3 localScale;
|
||||||
|
public SyncMode syncMode = SyncMode.Local;
|
||||||
|
public bool syncPosition = true;
|
||||||
|
public bool syncRotation = true;
|
||||||
|
public bool syncScale = false;
|
||||||
|
[HideInInspector] public SyncMode currMode = SyncMode.None;
|
||||||
|
internal float sendTime;
|
||||||
|
public float interval = 0.5f;
|
||||||
|
protected Net.Vector3 netPosition;
|
||||||
|
protected Net.Quaternion netRotation;
|
||||||
|
protected Net.Vector3 netLocalScale;
|
||||||
|
public float rate = 30f;//网络帧率, 一秒30次
|
||||||
|
public float lerpSpeed = 0.3f;
|
||||||
|
public bool fixedSync = true;
|
||||||
|
public float fixedSendTime = 1f;//固定发送时间
|
||||||
|
internal float fixedTime;
|
||||||
|
|
||||||
|
// Update is called once per frame
|
||||||
|
public virtual void Update()
|
||||||
|
{
|
||||||
|
if (netObj.Identity == -1 | currMode == SyncMode.None)
|
||||||
|
return;
|
||||||
|
if (currMode == SyncMode.Synchronized)
|
||||||
|
{
|
||||||
|
SyncTransform();
|
||||||
|
}
|
||||||
|
else if (Time.time > sendTime)
|
||||||
|
{
|
||||||
|
Check();
|
||||||
|
sendTime = Time.time + (1f / rate);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public virtual void Check()
|
||||||
|
{
|
||||||
|
if (transform.position != position | transform.rotation != rotation | transform.localScale != localScale | (Time.time > fixedTime & fixedSync))
|
||||||
|
{
|
||||||
|
position = transform.position;
|
||||||
|
rotation = transform.rotation;
|
||||||
|
localScale = transform.localScale;
|
||||||
|
fixedTime = Time.time + fixedSendTime;
|
||||||
|
StartSyncTransformState();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public virtual void StartSyncTransformState()
|
||||||
|
{
|
||||||
|
ClientBase.Instance.AddOperation(new Operation(Command.Transform, netObj.Identity, syncScale ? localScale : Net.Vector3.zero, syncPosition ? position : Net.Vector3.zero, syncRotation ? rotation : Net.Quaternion.zero)
|
||||||
|
{
|
||||||
|
cmd1 = (byte)currMode,
|
||||||
|
index = netObj.registerObjectIndex,
|
||||||
|
index1 = NetComponentID,
|
||||||
|
uid = ClientBase.Instance.UID
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
public virtual void SyncTransform()
|
||||||
|
{
|
||||||
|
if (syncPosition)
|
||||||
|
transform.position = Vector3.Lerp(transform.position, netPosition, lerpSpeed);
|
||||||
|
if (syncRotation)
|
||||||
|
if (netRotation != Net.Quaternion.identity)
|
||||||
|
transform.rotation = Quaternion.Lerp(transform.rotation, netRotation, lerpSpeed);
|
||||||
|
if (syncScale)
|
||||||
|
transform.localScale = netLocalScale;
|
||||||
|
}
|
||||||
|
|
||||||
|
public virtual void SyncControlTransform()
|
||||||
|
{
|
||||||
|
if (syncPosition)
|
||||||
|
{
|
||||||
|
position = netPosition;//位置要归位,要不然就会发送数据
|
||||||
|
transform.position = netPosition;
|
||||||
|
}
|
||||||
|
if (syncRotation)
|
||||||
|
{
|
||||||
|
rotation = netRotation;
|
||||||
|
transform.rotation = netRotation;
|
||||||
|
}
|
||||||
|
if (syncScale)
|
||||||
|
{
|
||||||
|
localScale = netLocalScale;
|
||||||
|
transform.localScale = netLocalScale;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void OnNetworkObjectInit(int identity)
|
||||||
|
{
|
||||||
|
currMode = syncMode;
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void OnNetworkObjectCreate(Operation opt)
|
||||||
|
{
|
||||||
|
if (opt.cmd == Command.Transform)
|
||||||
|
{
|
||||||
|
var mode1 = (SyncMode)opt.cmd1;
|
||||||
|
if (mode1 == SyncMode.Control | mode1 == SyncMode.SynchronizedAll)
|
||||||
|
currMode = SyncMode.SynchronizedAll;
|
||||||
|
else
|
||||||
|
currMode = SyncMode.Synchronized;
|
||||||
|
}
|
||||||
|
netPosition = opt.position;
|
||||||
|
netRotation = opt.rotation;
|
||||||
|
netLocalScale = opt.direction;
|
||||||
|
SyncControlTransform();
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void OnNetworkOperationHandler(Operation opt)
|
||||||
|
{
|
||||||
|
if (ClientBase.Instance.UID == opt.uid)
|
||||||
|
return;
|
||||||
|
sendTime = Time.time + interval;
|
||||||
|
netPosition = opt.position;
|
||||||
|
netRotation = opt.rotation;
|
||||||
|
netLocalScale = opt.direction;
|
||||||
|
if (currMode == SyncMode.SynchronizedAll | currMode == SyncMode.Control)
|
||||||
|
SyncControlTransform();
|
||||||
|
else if (currMode == SyncMode.None)
|
||||||
|
{
|
||||||
|
var mode1 = (SyncMode)opt.cmd1;
|
||||||
|
if (mode1 == SyncMode.Control | mode1 == SyncMode.SynchronizedAll)
|
||||||
|
currMode = SyncMode.SynchronizedAll;
|
||||||
|
else
|
||||||
|
currMode = SyncMode.Synchronized;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void SetNetworkPosition(Net.Vector3 position)
|
||||||
|
{
|
||||||
|
netPosition = position;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void SetNetworkRotation(Net.Quaternion rotation)
|
||||||
|
{
|
||||||
|
netRotation = rotation;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void SetNetworkPositionAndRotation(Net.Vector3 position, Net.Quaternion rotation)
|
||||||
|
{
|
||||||
|
netPosition = position;
|
||||||
|
netRotation = rotation;
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void OnDestroy()
|
||||||
|
{
|
||||||
|
base.OnDestroy();
|
||||||
|
if (ClientBase.Instance == null)
|
||||||
|
return;
|
||||||
|
//如果在退出游戏或者退出场景后不让物体被销毁,则需要查找netobj组件设置Identity等于-1,或者查找此组件设置currMode等于None,或者在点击处理的时候调用ClientBase.Instance.Close方法
|
||||||
|
if ((currMode == SyncMode.SynchronizedAll | currMode == SyncMode.Control) & netObj.Identity != -1 & ClientBase.Instance.Connected)
|
||||||
|
ClientBase.Instance.AddOperation(new Operation(Command.Destroy, netObj.Identity));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
|
@ -0,0 +1,159 @@
|
||||||
|
#if UNITY_STANDALONE || UNITY_ANDROID || UNITY_IOS || UNITY_WSA || UNITY_WEBGL
|
||||||
|
namespace Net.UnityComponent
|
||||||
|
{
|
||||||
|
using Net.Component;
|
||||||
|
using Net.Share;
|
||||||
|
using global::System;
|
||||||
|
using UnityEngine;
|
||||||
|
using Net.Client;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 网络Transform同步组件基类
|
||||||
|
/// </summary>
|
||||||
|
[DefaultExecutionOrder(1000)]
|
||||||
|
public class NetworkTransformMulti : NetworkTransformBase
|
||||||
|
{
|
||||||
|
public ChildTransform[] childs;
|
||||||
|
|
||||||
|
public override void Start()
|
||||||
|
{
|
||||||
|
base.Start();
|
||||||
|
for (int i = 0; i < childs.Length; i++)
|
||||||
|
{
|
||||||
|
childs[i].Init(i + 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void Update()
|
||||||
|
{
|
||||||
|
if (netObj.Identity == -1 | currMode == SyncMode.None)
|
||||||
|
return;
|
||||||
|
if (currMode == SyncMode.Synchronized)
|
||||||
|
{
|
||||||
|
SyncTransform();
|
||||||
|
for (int i = 0; i < childs.Length; i++)
|
||||||
|
{
|
||||||
|
childs[i].SyncTransform();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (Time.time > sendTime)
|
||||||
|
{
|
||||||
|
Check();
|
||||||
|
for (int i = 0; i < childs.Length; i++)
|
||||||
|
{
|
||||||
|
childs[i].Check(netObj.Identity, netObj.registerObjectIndex, NetComponentID);
|
||||||
|
}
|
||||||
|
sendTime = Time.time + (1f / rate);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void StartSyncTransformState()
|
||||||
|
{
|
||||||
|
ClientBase.Instance.AddOperation(new Operation(Command.Transform, netObj.Identity, syncScale ? localScale : Net.Vector3.zero, syncPosition ? position : Net.Vector3.zero, syncRotation ? rotation : Net.Quaternion.zero)
|
||||||
|
{
|
||||||
|
cmd1 = (byte)currMode,
|
||||||
|
index = netObj.registerObjectIndex,
|
||||||
|
index1 = NetComponentID,
|
||||||
|
uid = ClientBase.Instance.UID
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void OnNetworkOperationHandler(Operation opt)
|
||||||
|
{
|
||||||
|
if (ClientBase.Instance.UID == opt.uid)
|
||||||
|
return;
|
||||||
|
sendTime = Time.time + interval;
|
||||||
|
if (opt.index2 == 0)
|
||||||
|
{
|
||||||
|
netPosition = opt.position;
|
||||||
|
netRotation = opt.rotation;
|
||||||
|
netLocalScale = opt.direction;
|
||||||
|
if (currMode == SyncMode.SynchronizedAll | currMode == SyncMode.Control)
|
||||||
|
SyncControlTransform();
|
||||||
|
else if (currMode == SyncMode.None)
|
||||||
|
{
|
||||||
|
var mode1 = (SyncMode)opt.cmd1;
|
||||||
|
if (mode1 == SyncMode.Control | mode1 == SyncMode.SynchronizedAll)
|
||||||
|
currMode = SyncMode.SynchronizedAll;
|
||||||
|
else
|
||||||
|
currMode = SyncMode.Synchronized;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
var child = childs[opt.index2 - 1];
|
||||||
|
child.netPosition = opt.position;
|
||||||
|
child.netRotation = opt.rotation;
|
||||||
|
child.netLocalScale = opt.direction;
|
||||||
|
if (child.mode == SyncMode.SynchronizedAll | child.mode == SyncMode.Control)
|
||||||
|
child.SyncControlTransform();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
[Serializable]
|
||||||
|
public class ChildTransform
|
||||||
|
{
|
||||||
|
public string name;
|
||||||
|
public Transform transform;
|
||||||
|
internal Net.Vector3 position;
|
||||||
|
internal Net.Quaternion rotation;
|
||||||
|
internal Net.Vector3 localScale;
|
||||||
|
public SyncMode mode = SyncMode.Control;
|
||||||
|
public bool syncPosition = true;
|
||||||
|
public bool syncRotation = true;
|
||||||
|
public bool syncScale = false;
|
||||||
|
public int identity = -1;//自身id
|
||||||
|
internal Net.Vector3 netPosition;
|
||||||
|
internal Net.Quaternion netRotation;
|
||||||
|
internal Net.Vector3 netLocalScale;
|
||||||
|
|
||||||
|
internal void Init(int identity)
|
||||||
|
{
|
||||||
|
this.identity = identity;
|
||||||
|
position = transform.localPosition;
|
||||||
|
rotation = transform.localRotation;
|
||||||
|
localScale = transform.localScale;
|
||||||
|
}
|
||||||
|
|
||||||
|
internal void Check(int identity, int index, int netIndex)
|
||||||
|
{
|
||||||
|
if (transform.localPosition != position | transform.localRotation != rotation | transform.localScale != localScale)
|
||||||
|
{
|
||||||
|
position = transform.localPosition;
|
||||||
|
rotation = transform.localRotation;
|
||||||
|
localScale = transform.localScale;
|
||||||
|
ClientBase.Instance.AddOperation(new Operation(Command.Transform, identity, syncScale ? localScale : Net.Vector3.zero, syncPosition ? position : Net.Vector3.zero, syncRotation ? rotation : Net.Quaternion.zero)
|
||||||
|
{
|
||||||
|
cmd1 = (byte)mode,
|
||||||
|
uid = ClientBase.Instance.UID,
|
||||||
|
index = index,
|
||||||
|
index1 = netIndex,
|
||||||
|
index2 = this.identity
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void SyncTransform()
|
||||||
|
{
|
||||||
|
if (syncPosition)
|
||||||
|
transform.localPosition = Vector3.Lerp(transform.localPosition, netPosition, 0.3f);
|
||||||
|
if (syncRotation)
|
||||||
|
if (netRotation != Net.Quaternion.identity)
|
||||||
|
transform.localRotation = Quaternion.Lerp(transform.localRotation, netRotation, 0.3f);
|
||||||
|
if (syncScale)
|
||||||
|
transform.localScale = netLocalScale;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void SyncControlTransform()
|
||||||
|
{
|
||||||
|
if (syncPosition)
|
||||||
|
transform.localPosition = netPosition;
|
||||||
|
if (syncRotation)
|
||||||
|
transform.localRotation = netRotation;
|
||||||
|
if (syncScale)
|
||||||
|
transform.localScale = netLocalScale;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
|
@ -0,0 +1,514 @@
|
||||||
|
#if UNITY_EDITOR
|
||||||
|
using Net.Helper;
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.IO;
|
||||||
|
using System.Reflection;
|
||||||
|
using System.Text;
|
||||||
|
using UnityEditor;
|
||||||
|
using UnityEngine;
|
||||||
|
using static Fast2BuildTools2;
|
||||||
|
using Object = UnityEngine.Object;
|
||||||
|
|
||||||
|
public class BuildComponentTools : EditorWindow
|
||||||
|
{
|
||||||
|
private Data data = new Data();
|
||||||
|
private Object component;
|
||||||
|
private Object oldComponent;
|
||||||
|
private FoldoutData foldout;
|
||||||
|
private Vector2 scrollPosition1;
|
||||||
|
|
||||||
|
[MenuItem("GameDesigner/Network/BuildComponentTools")]
|
||||||
|
public static void Init()
|
||||||
|
{
|
||||||
|
GetWindow<BuildComponentTools>("BuildComponentTools", true);
|
||||||
|
}
|
||||||
|
private void OnEnable()
|
||||||
|
{
|
||||||
|
LoadData();
|
||||||
|
}
|
||||||
|
private void OnDisable()
|
||||||
|
{
|
||||||
|
SaveData();
|
||||||
|
}
|
||||||
|
void OnGUI()
|
||||||
|
{
|
||||||
|
component = EditorGUILayout.ObjectField("组件", component, typeof(Object), true);
|
||||||
|
if (component != oldComponent)
|
||||||
|
{
|
||||||
|
oldComponent = component;
|
||||||
|
if (component != null)
|
||||||
|
{
|
||||||
|
var type = component.GetType();
|
||||||
|
//var fields = type.GetFields(BindingFlags.Public | BindingFlags.Instance);
|
||||||
|
var properties = type.GetProperties(BindingFlags.Public | BindingFlags.Instance);
|
||||||
|
var methods = type.GetMethods(BindingFlags.Instance | BindingFlags.Public);
|
||||||
|
var fields1 = new List<FieldData>();
|
||||||
|
//foreach (var item in fields)
|
||||||
|
//{
|
||||||
|
// fields1.Add(new FieldData() { name = item.Name, serialize = true });
|
||||||
|
//}
|
||||||
|
foreach (var item in properties)
|
||||||
|
{
|
||||||
|
if (!item.CanRead | !item.CanWrite)
|
||||||
|
continue;
|
||||||
|
if (item.GetIndexParameters().Length > 0)
|
||||||
|
continue;
|
||||||
|
if (item.GetCustomAttribute<ObsoleteAttribute>() != null)
|
||||||
|
continue;
|
||||||
|
var ptype = item.PropertyType;
|
||||||
|
var code = Type.GetTypeCode(ptype);
|
||||||
|
if (code == TypeCode.Object & ptype != typeof(Vector2) & ptype != typeof(Vector3) & ptype != typeof(Vector4) &
|
||||||
|
ptype != typeof(Rect) & ptype != typeof(Quaternion) & ptype != typeof(Color)
|
||||||
|
& ptype != typeof(Color32) & ptype != typeof(Net.Vector2) & ptype != typeof(Net.Vector3)
|
||||||
|
& ptype != typeof(Net.Vector4) & ptype != typeof(Net.Rect) & ptype != typeof(Net.Quaternion)
|
||||||
|
& ptype != typeof(Net.Color) & ptype != typeof(Net.Color32) & ptype != typeof(Object) & !ptype.IsSubclassOf(typeof(Object)))
|
||||||
|
continue;
|
||||||
|
fields1.Add(new FieldData() { name = item.Name });
|
||||||
|
}
|
||||||
|
for (int i = 0; i < methods.Length; i++)
|
||||||
|
{
|
||||||
|
var met = methods[i];
|
||||||
|
if (met.MethodImplementationFlags == MethodImplAttributes.InternalCall | met.Name.Contains("get_") | met.Name.Contains("set_") |
|
||||||
|
met.GetCustomAttribute<ObsoleteAttribute>() != null | met.IsGenericMethod)
|
||||||
|
continue;
|
||||||
|
var pars = met.GetParameters();
|
||||||
|
bool not = false;
|
||||||
|
foreach (var item in pars)
|
||||||
|
{
|
||||||
|
var ptype = item.ParameterType;
|
||||||
|
var code = Type.GetTypeCode(ptype);
|
||||||
|
if (code == TypeCode.Object & ptype != typeof(Vector2) & ptype != typeof(Vector3) & ptype != typeof(Vector4) &
|
||||||
|
ptype != typeof(Rect) & ptype != typeof(Quaternion) & ptype != typeof(Color)
|
||||||
|
& ptype != typeof(Color32) & ptype != typeof(Net.Vector2) & ptype != typeof(Net.Vector3)
|
||||||
|
& ptype != typeof(Net.Vector4) & ptype != typeof(Net.Rect) & ptype != typeof(Net.Quaternion)
|
||||||
|
& ptype != typeof(Net.Color) & ptype != typeof(Net.Color32) //& ptype != typeof(Object) & !ptype.IsSubclassOf(typeof(Object))
|
||||||
|
)
|
||||||
|
{
|
||||||
|
not = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (not)
|
||||||
|
continue;
|
||||||
|
fields1.Add(new FieldData() { name = met.ToString() });
|
||||||
|
}
|
||||||
|
foldout = new FoldoutData() { name = type.Name, fields = fields1, foldout = true };
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (foldout != null)
|
||||||
|
{
|
||||||
|
scrollPosition1 = GUILayout.BeginScrollView(scrollPosition1, false, true);
|
||||||
|
var rect = EditorGUILayout.GetControlRect();
|
||||||
|
foldout.foldout = EditorGUI.Foldout(rect, foldout.foldout, foldout.name + "", true);
|
||||||
|
if (foldout.foldout)
|
||||||
|
{
|
||||||
|
EditorGUI.indentLevel = 1;
|
||||||
|
for (int i = 0; i < foldout.fields.Count; i++)
|
||||||
|
{
|
||||||
|
var rect1 = EditorGUILayout.GetControlRect();
|
||||||
|
rect1.x += 20;
|
||||||
|
var width = rect1.width;
|
||||||
|
rect1.width = 180;
|
||||||
|
foldout.fields[i].select = GUI.Toolbar(rect1, foldout.fields[i].select, new string[] { "同步调用", "本地调用", "忽略" });
|
||||||
|
rect1.x += 200;
|
||||||
|
rect1.width = width - 200;
|
||||||
|
GUIStyle titleStyle2 = new GUIStyle();
|
||||||
|
switch (foldout.fields[i].select)
|
||||||
|
{
|
||||||
|
case 0:
|
||||||
|
titleStyle2.normal.textColor = Color.white;
|
||||||
|
break;
|
||||||
|
case 1:
|
||||||
|
titleStyle2.normal.textColor = Color.green;
|
||||||
|
break;
|
||||||
|
case 2:
|
||||||
|
titleStyle2.normal.textColor = Color.red;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
GUI.Label(rect1, foldout.fields[i].name, titleStyle2);
|
||||||
|
|
||||||
|
}
|
||||||
|
EditorGUI.indentLevel = 0;
|
||||||
|
}
|
||||||
|
if (rect.Contains(Event.current.mousePosition) & Event.current.button == 1)
|
||||||
|
{
|
||||||
|
GenericMenu menu = new GenericMenu();
|
||||||
|
menu.AddItem(new GUIContent("全部同步调用勾上"), false, () =>
|
||||||
|
{
|
||||||
|
foldout.fields.ForEach(item => item.select = 0);
|
||||||
|
});
|
||||||
|
menu.AddItem(new GUIContent("全部本地调用勾上"), false, () =>
|
||||||
|
{
|
||||||
|
foldout.fields.ForEach(item => item.select = 1);
|
||||||
|
});
|
||||||
|
menu.AddItem(new GUIContent("智能本地调用勾上"), false, () =>
|
||||||
|
{
|
||||||
|
foldout.fields.ForEach(item => {
|
||||||
|
if (item.name.Contains("Get") | item.name.Contains("Is"))
|
||||||
|
item.select = 1;
|
||||||
|
});
|
||||||
|
});
|
||||||
|
menu.AddItem(new GUIContent("全部取消"), false, () =>
|
||||||
|
{
|
||||||
|
foldout.fields.ForEach(item => item.select = 2);
|
||||||
|
});
|
||||||
|
menu.ShowAsContext();
|
||||||
|
}
|
||||||
|
GUILayout.EndScrollView();
|
||||||
|
}
|
||||||
|
GUILayout.BeginHorizontal();
|
||||||
|
EditorGUILayout.LabelField("保存路径:", data.savePath);
|
||||||
|
if (GUILayout.Button("选择路径", GUILayout.Width(100)))
|
||||||
|
{
|
||||||
|
data.savePath = EditorUtility.OpenFolderPanel("保存路径", "", "");
|
||||||
|
SaveData();
|
||||||
|
}
|
||||||
|
GUILayout.EndHorizontal();
|
||||||
|
if (GUILayout.Button("生成同步组件脚本", GUILayout.Height(40)))
|
||||||
|
{
|
||||||
|
if (string.IsNullOrEmpty(data.savePath))
|
||||||
|
{
|
||||||
|
EditorUtility.DisplayDialog("提示", "请选择生成脚本路径!", "确定");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (component == null)
|
||||||
|
{
|
||||||
|
EditorUtility.DisplayDialog("提示", "请选择unity组件!", "确定");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
var type = component.GetType();
|
||||||
|
var str = BuildNew(type, foldout.fields.ConvertAll((item) => item.select == 2 ? item.name : ""), foldout.fields.ConvertAll((item) => item.select == 1 ? item.name : ""));
|
||||||
|
File.WriteAllText(data.savePath + $"//Network{type.Name}.cs", str.ToString());
|
||||||
|
Debug.Log("生成脚本成功!");
|
||||||
|
AssetDatabase.Refresh();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static StringBuilder BuildNew(Type type, List<string> ignores, List<string> immediatelys)
|
||||||
|
{
|
||||||
|
var templateCode = @"#if UNITY_STANDALONE || UNITY_ANDROID || UNITY_IOS || UNITY_WSA || UNITY_WEBGL
|
||||||
|
using Net.Client;
|
||||||
|
using Net.Share;
|
||||||
|
using Net.Component;
|
||||||
|
using Net.UnityComponent;
|
||||||
|
using UnityEngine;
|
||||||
|
using Net.System;
|
||||||
|
using static Net.Serialize.NetConvertFast2;
|
||||||
|
|
||||||
|
namespace BuildComponent
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// {TypeName1}同步组件, 此代码由BuildComponentTools工具生成, 如果同步发生相互影响的字段或属性, 请自行检查处理一下!
|
||||||
|
/// </summary>
|
||||||
|
[RequireComponent(typeof({TypeName}))]
|
||||||
|
public class Network{TypeName1} : NetworkBehaviour
|
||||||
|
{
|
||||||
|
private {TypeName} self;
|
||||||
|
public bool autoCheck;
|
||||||
|
private object[] fields;
|
||||||
|
private int[] eventsId;
|
||||||
|
|
||||||
|
public void Awake()
|
||||||
|
{
|
||||||
|
self = GetComponent<{TypeName}>();
|
||||||
|
[Split]
|
||||||
|
fields = new object[{FieldSize}];
|
||||||
|
eventsId = new int[{FieldSize}];
|
||||||
|
[Split]
|
||||||
|
fields[{FieldIndex}] = self.{TypeFieldName};
|
||||||
|
[Split]
|
||||||
|
}
|
||||||
|
|
||||||
|
[Split]
|
||||||
|
public {PropertyType} {TypeFieldName}
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
return self.{TypeFieldName};
|
||||||
|
}
|
||||||
|
set
|
||||||
|
{
|
||||||
|
if (value.Equals({FieldName}))
|
||||||
|
return;
|
||||||
|
{FieldName} = value;
|
||||||
|
self.{TypeFieldName} = value;
|
||||||
|
ClientBase.Instance.AddOperation(new Operation(Command.BuildComponent, netObj.Identity)
|
||||||
|
{
|
||||||
|
index = netObj.registerObjectIndex,
|
||||||
|
index1 = Index,
|
||||||
|
index2 = {FieldIndex},
|
||||||
|
buffer = SerializeObject(value).ToArray(true),
|
||||||
|
uid = ClientBase.Instance.UID
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
[Split]
|
||||||
|
public override void OnPropertyAutoCheck()
|
||||||
|
{
|
||||||
|
if (!autoCheck)
|
||||||
|
return;
|
||||||
|
[Split]
|
||||||
|
{TypeFieldName} = {TypeFieldName};
|
||||||
|
[Split]
|
||||||
|
}
|
||||||
|
[Split]
|
||||||
|
public void {FuncName}({ParsString} bool always = false, int executeNumber = 0, float time = 0)
|
||||||
|
{
|
||||||
|
if ({Condition} !always) return;
|
||||||
|
{SetPars}
|
||||||
|
var buffer = SerializeModel(new RPCModel() { pars = new object[] { {Params} } });
|
||||||
|
ClientBase.Instance.AddOperation(new Operation(Command.BuildComponent, netObj.Identity)
|
||||||
|
{
|
||||||
|
index = netObj.registerObjectIndex,
|
||||||
|
index1 = Index,
|
||||||
|
index2 = {FieldIndex},
|
||||||
|
buffer = buffer
|
||||||
|
});
|
||||||
|
if (executeNumber > 0)
|
||||||
|
{
|
||||||
|
ThreadManager.Event.RemoveEvent(eventsId[{EIDIndex}]);
|
||||||
|
eventsId[{EIDIndex}] = ThreadManager.Event.AddEvent(time, executeNumber, (obj)=> {
|
||||||
|
{FuncName}({Params} true, 0, 0);
|
||||||
|
}, null);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
[Split]
|
||||||
|
public {ReturnType} {FuncName}({ParsString})
|
||||||
|
{
|
||||||
|
{Return}self.{FuncName}({Params});
|
||||||
|
}
|
||||||
|
[Split]
|
||||||
|
public override void OnNetworkOperationHandler(Operation opt)
|
||||||
|
{
|
||||||
|
switch (opt.index2)
|
||||||
|
{
|
||||||
|
[Split]
|
||||||
|
case {FieldIndex1}:
|
||||||
|
{
|
||||||
|
if (opt.uid == ClientBase.Instance.UID)
|
||||||
|
return;
|
||||||
|
var {TypeFieldName} = DeserializeObject<{FieldType1}>(new Segment(opt.buffer, false));
|
||||||
|
{FieldName} = {TypeFieldName};
|
||||||
|
self.{TypeFieldName} = {TypeFieldName};
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
[Split]
|
||||||
|
case {FieldIndex1}:
|
||||||
|
{
|
||||||
|
self.{FuncName}();
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
[Split]
|
||||||
|
case {FieldIndex1}:
|
||||||
|
{
|
||||||
|
var segment = new Segment(opt.buffer, false);
|
||||||
|
var data = DeserializeModel(segment);
|
||||||
|
{SetPars}
|
||||||
|
self.{FuncName}({Params});
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
[Split]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
" + @"#endif";
|
||||||
|
|
||||||
|
var properties = type.GetProperties(BindingFlags.Instance | BindingFlags.Public);
|
||||||
|
var methods = type.GetMethods(BindingFlags.Instance | BindingFlags.Public);
|
||||||
|
StringBuilder sb = new StringBuilder();
|
||||||
|
StringBuilder sb1 = new StringBuilder();
|
||||||
|
StringBuilder sb2 = new StringBuilder();
|
||||||
|
StringBuilder sb3 = new StringBuilder();
|
||||||
|
StringBuilder sb4 = new StringBuilder();
|
||||||
|
StringBuilder sb5 = new StringBuilder();
|
||||||
|
|
||||||
|
templateCode = templateCode.Replace("{TypeName1}", $"{type.Name}");
|
||||||
|
templateCode = templateCode.Replace("{TypeName}", $"{type.FullName}");
|
||||||
|
|
||||||
|
var blockCodes = templateCode.Split(new string[] { "[Split]" }, 0);
|
||||||
|
blockCodes[0] = blockCodes[0].Remove(blockCodes[0].Length - 2, 2);
|
||||||
|
sb.Append(blockCodes[0]);
|
||||||
|
|
||||||
|
int parNum = 0;
|
||||||
|
for (int i = 0; i < properties.Length; i++)
|
||||||
|
{
|
||||||
|
var item = properties[i];
|
||||||
|
if (ignores.Contains(item.Name))
|
||||||
|
continue;
|
||||||
|
if (!item.CanRead | !item.CanWrite | item.GetCustomAttribute<ObsoleteAttribute>() != null)
|
||||||
|
continue;
|
||||||
|
var ptype = item.PropertyType;
|
||||||
|
var code = Type.GetTypeCode(ptype);
|
||||||
|
if (code == TypeCode.Object & ptype != typeof(Vector2) & ptype != typeof(Vector3) & ptype != typeof(Vector4) &
|
||||||
|
ptype != typeof(Rect) & ptype != typeof(Quaternion) & ptype != typeof(Color)
|
||||||
|
& ptype != typeof(Color32) & ptype != typeof(Net.Vector2) & ptype != typeof(Net.Vector3)
|
||||||
|
& ptype != typeof(Net.Vector4) & ptype != typeof(Net.Rect) & ptype != typeof(Net.Quaternion)
|
||||||
|
& ptype != typeof(Net.Color) & ptype != typeof(Net.Color32) & ptype != typeof(UnityEngine.Object) & !ptype.IsSubclassOf(typeof(UnityEngine.Object))
|
||||||
|
)
|
||||||
|
continue;
|
||||||
|
parNum++;
|
||||||
|
var blockCode = blockCodes[2];
|
||||||
|
blockCode = blockCode.Replace("{FieldIndex}", $"{parNum}");
|
||||||
|
blockCode = blockCode.Replace("{TypeFieldName}", $"{item.Name}");
|
||||||
|
blockCode = blockCode.Remove(blockCode.Length - 2, 2);
|
||||||
|
sb1.Append(blockCode);
|
||||||
|
|
||||||
|
blockCode = blockCodes[4];
|
||||||
|
blockCode = blockCode.Replace("{PropertyType}", $"{item.PropertyType.FullName}");
|
||||||
|
blockCode = blockCode.Replace("{TypeFieldName}", $"{item.Name}");
|
||||||
|
blockCode = blockCode.Replace("{FieldName}", $"fields[{parNum}]");
|
||||||
|
blockCode = blockCode.Replace("{FieldIndex}", $"{parNum}");
|
||||||
|
blockCode = blockCode.Remove(blockCode.Length - 2, 2);
|
||||||
|
sb2.Append(blockCode);
|
||||||
|
|
||||||
|
blockCode = blockCodes[6];
|
||||||
|
blockCode = blockCode.Replace("{TypeFieldName}", $"{item.Name}");
|
||||||
|
blockCode = blockCode.Remove(blockCode.Length - 2, 2);
|
||||||
|
sb3.Append(blockCode);
|
||||||
|
|
||||||
|
blockCode = blockCodes[11];
|
||||||
|
blockCode = blockCode.Replace("{FieldIndex1}", $"{parNum}");
|
||||||
|
blockCode = blockCode.Replace("{FieldName}", $"fields[{parNum}]");
|
||||||
|
blockCode = blockCode.Replace("{FieldType1}", $"{item.PropertyType.FullName}");
|
||||||
|
blockCode = blockCode.Replace("{TypeFieldName}", $"{item.Name}");
|
||||||
|
blockCode = blockCode.Remove(blockCode.Length - 2, 2);
|
||||||
|
sb5.Append(blockCode);
|
||||||
|
}
|
||||||
|
for (int i = 0; i < methods.Length; i++)
|
||||||
|
{
|
||||||
|
var met = methods[i];
|
||||||
|
var metName = met.ToString();
|
||||||
|
if (ignores.Contains(metName))
|
||||||
|
continue;
|
||||||
|
if (met.MethodImplementationFlags == MethodImplAttributes.InternalCall | met.Name.Contains("get_") | met.Name.Contains("set_") |
|
||||||
|
met.GetCustomAttribute<ObsoleteAttribute>() != null | met.IsGenericMethod)
|
||||||
|
continue;
|
||||||
|
var pars = met.GetParameters();
|
||||||
|
bool not = false;
|
||||||
|
foreach (var item in pars)
|
||||||
|
{
|
||||||
|
var ptype = item.ParameterType;
|
||||||
|
var code = Type.GetTypeCode(ptype);
|
||||||
|
if (code == TypeCode.Object & ptype != typeof(Vector2) & ptype != typeof(Vector3) & ptype != typeof(Vector4) &
|
||||||
|
ptype != typeof(Rect) & ptype != typeof(Quaternion) & ptype != typeof(Color)
|
||||||
|
& ptype != typeof(Color32) & ptype != typeof(Net.Vector2) & ptype != typeof(Net.Vector3)
|
||||||
|
& ptype != typeof(Net.Vector4) & ptype != typeof(Net.Rect) & ptype != typeof(Net.Quaternion)
|
||||||
|
& ptype != typeof(Net.Color) & ptype != typeof(Net.Color32) //& ptype != typeof(Object) & !ptype.IsSubclassOf(typeof(Object))
|
||||||
|
)
|
||||||
|
{
|
||||||
|
not = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (not)
|
||||||
|
continue;
|
||||||
|
string blockCode;
|
||||||
|
var parsStr = "";
|
||||||
|
var conditionStr = "";
|
||||||
|
var setValueStr = "";
|
||||||
|
var paramsStr = "";
|
||||||
|
var setValueStr1 = "";
|
||||||
|
parNum++;
|
||||||
|
var metIndex = parNum;
|
||||||
|
foreach (var item in pars)
|
||||||
|
{
|
||||||
|
parNum++;
|
||||||
|
parsStr += $"{item.ParameterType.FullName} {item.Name},";
|
||||||
|
conditionStr += $"{item.Name}.Equals(fields[{parNum}]) & ";
|
||||||
|
setValueStr += $"fields[{parNum}] = {item.Name};\r\n\t\t\t";
|
||||||
|
paramsStr += $"{item.Name},";
|
||||||
|
setValueStr1 += $"var {item.Name} = ({item.ParameterType.FullName})(fields[{parNum}] = data.Obj);\r\n\t\t\t\t\t\t";
|
||||||
|
}
|
||||||
|
if (setValueStr.Length > 0)
|
||||||
|
setValueStr = setValueStr.Remove(setValueStr.Length - 5, 5);
|
||||||
|
if (setValueStr1.Length > 0)
|
||||||
|
setValueStr1 = setValueStr1.Remove(setValueStr1.Length - 8, 8);
|
||||||
|
|
||||||
|
if (immediatelys.Contains(metName))
|
||||||
|
{
|
||||||
|
parsStr = parsStr.TrimEnd(',');
|
||||||
|
paramsStr = paramsStr.TrimEnd(',');
|
||||||
|
blockCode = blockCodes[9];
|
||||||
|
blockCode = blockCode.Replace("{FuncName}", $"{met.Name}");
|
||||||
|
blockCode = blockCode.Replace("{ParsString}", $"{parsStr}");
|
||||||
|
blockCode = blockCode.Replace("{ReturnType}", $"{(met.ReturnType == typeof(void) ? "void" : met.ReturnType.FullName)}");
|
||||||
|
blockCode = blockCode.Replace("{Return}", $"{(met.ReturnType == typeof(void) ? "" : "return ")}");
|
||||||
|
blockCode = blockCode.Replace("{Params}", $"{paramsStr}");
|
||||||
|
blockCode = blockCode.Remove(blockCode.Length - 2, 2);
|
||||||
|
sb4.Append(blockCode);
|
||||||
|
parNum = metIndex - 1;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
blockCode = blockCodes[8];
|
||||||
|
blockCode = blockCode.Replace("{FuncName}", $"{met.Name}");
|
||||||
|
blockCode = blockCode.Replace("{ParsString}", $"{parsStr}");
|
||||||
|
blockCode = blockCode.Replace("{Condition}", $"{conditionStr}");
|
||||||
|
blockCode = blockCode.Replace("{SetPars}", $"{setValueStr}");
|
||||||
|
blockCode = blockCode.Replace("{Params}", $"{paramsStr}");
|
||||||
|
blockCode = blockCode.Replace("{FieldIndex}", $"{metIndex}");
|
||||||
|
|
||||||
|
blockCode = blockCode.Replace("{EIDIndex}", $"{metIndex}");
|
||||||
|
|
||||||
|
blockCode = blockCode.Remove(blockCode.Length - 2, 2);
|
||||||
|
sb4.Append(blockCode);
|
||||||
|
|
||||||
|
if (pars.Length == 0)
|
||||||
|
{
|
||||||
|
blockCode = blockCodes[12];
|
||||||
|
blockCode = blockCode.Replace("{FieldIndex1}", $"{metIndex}");
|
||||||
|
blockCode = blockCode.Replace("{FuncName}", $"{met.Name}");
|
||||||
|
blockCode = blockCode.Remove(blockCode.Length - 2, 2);
|
||||||
|
sb5.Append(blockCode);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
paramsStr = paramsStr.TrimEnd(',');
|
||||||
|
blockCode = blockCodes[13];
|
||||||
|
blockCode = blockCode.Replace("{FieldIndex1}", $"{metIndex}");
|
||||||
|
blockCode = blockCode.Replace("{FuncName}", $"{met.Name}");
|
||||||
|
blockCode = blockCode.Replace("{Params}", $"{paramsStr}");
|
||||||
|
blockCode = blockCode.Replace("{SetPars}", $"{setValueStr1}");
|
||||||
|
blockCode = blockCode.Remove(blockCode.Length - 2, 2);
|
||||||
|
sb5.Append(blockCode);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var blockCodeX = blockCodes[1];
|
||||||
|
blockCodeX = blockCodeX.Replace("{FieldSize}", $"{parNum}");
|
||||||
|
blockCodeX = blockCodeX.Remove(blockCodeX.Length - 2, 2);
|
||||||
|
sb.Append(blockCodeX);
|
||||||
|
sb.Append(sb1.ToString());
|
||||||
|
sb.Append(blockCodes[3]);
|
||||||
|
|
||||||
|
sb.Append(sb2.ToString());
|
||||||
|
|
||||||
|
sb.Append(blockCodes[5]);
|
||||||
|
sb.Append(sb3.ToString());
|
||||||
|
sb.Append(blockCodes[7]);
|
||||||
|
|
||||||
|
sb.Append(sb4.ToString());
|
||||||
|
|
||||||
|
sb.Append(blockCodes[10]);
|
||||||
|
sb.Append(sb5.ToString());
|
||||||
|
sb.Append(blockCodes[14]);
|
||||||
|
|
||||||
|
return sb;
|
||||||
|
}
|
||||||
|
|
||||||
|
void LoadData()
|
||||||
|
{
|
||||||
|
data = PersistHelper.Deserialize<Data>("networkComponentBuild.json");
|
||||||
|
}
|
||||||
|
void SaveData()
|
||||||
|
{
|
||||||
|
PersistHelper.Serialize(data, "networkComponentBuild.json");
|
||||||
|
}
|
||||||
|
internal class Data
|
||||||
|
{
|
||||||
|
public string savePath, savePath1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
|
@ -0,0 +1,36 @@
|
||||||
|
using UnityEngine;
|
||||||
|
using UnityEditor;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 只显示不能修改属性绘制
|
||||||
|
/// </summary>
|
||||||
|
[CustomPropertyDrawer(typeof(DisplayOnly))]
|
||||||
|
public class ReadOnlyDrawer : PropertyDrawer
|
||||||
|
{
|
||||||
|
public override float GetPropertyHeight(SerializedProperty property, GUIContent label)
|
||||||
|
{
|
||||||
|
return EditorGUI.GetPropertyHeight(property, label, true);
|
||||||
|
}
|
||||||
|
public override void OnGUI(Rect position, SerializedProperty property, GUIContent label)
|
||||||
|
{
|
||||||
|
GUI.enabled = false;
|
||||||
|
EditorGUI.PropertyField(position, property, label, true);
|
||||||
|
GUI.enabled = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
///<summary>
|
||||||
|
///绘制多选属性
|
||||||
|
///</summary>
|
||||||
|
[CustomPropertyDrawer(typeof(EnumFlags))]
|
||||||
|
public class EnumFlagsDrawer : PropertyDrawer
|
||||||
|
{
|
||||||
|
public override void OnGUI(Rect position, SerializedProperty property, GUIContent label)
|
||||||
|
{
|
||||||
|
property.intValue = EditorGUI.MaskField(position, label, property.intValue, property.enumNames);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,25 @@
|
||||||
|
#if (UNITY_STANDALONE || UNITY_ANDROID || UNITY_IOS || UNITY_WSA || UNITY_WEBGL) && UNITY_EDITOR
|
||||||
|
using Net.UnityComponent;
|
||||||
|
using UnityEditor;
|
||||||
|
using UnityEngine;
|
||||||
|
|
||||||
|
[CustomEditor(typeof(NetworkObject))]
|
||||||
|
[CanEditMultipleObjects]
|
||||||
|
public class NetworkObjectEdit : Editor
|
||||||
|
{
|
||||||
|
private NetworkObject no;
|
||||||
|
|
||||||
|
private void OnEnable()
|
||||||
|
{
|
||||||
|
no = target as NetworkObject;
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void OnInspectorGUI()
|
||||||
|
{
|
||||||
|
base.OnInspectorGUI();
|
||||||
|
GUI.enabled = false;
|
||||||
|
EditorGUILayout.LabelField("Network Identity", no.Identity.ToString());
|
||||||
|
GUI.enabled = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
|
@ -0,0 +1,31 @@
|
||||||
|
#if (UNITY_STANDALONE || UNITY_ANDROID || UNITY_IOS || UNITY_WSA || UNITY_WEBGL) && UNITY_EDITOR
|
||||||
|
using Net.UnityComponent;
|
||||||
|
using UnityEditor;
|
||||||
|
using UnityEngine;
|
||||||
|
|
||||||
|
[CustomEditor(typeof(NetworkSceneManager))]
|
||||||
|
[CanEditMultipleObjects]
|
||||||
|
public class NetworkSceneManagerEdit : Editor
|
||||||
|
{
|
||||||
|
private NetworkSceneManager nt;
|
||||||
|
|
||||||
|
private void OnEnable()
|
||||||
|
{
|
||||||
|
nt = target as NetworkSceneManager;
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void OnInspectorGUI()
|
||||||
|
{
|
||||||
|
base.OnInspectorGUI();
|
||||||
|
if (GUILayout.Button("ÉèÖÃregisterObjectIndex"))
|
||||||
|
{
|
||||||
|
for (int i = 0; i < nt.registerObjects.Count; i++)
|
||||||
|
{
|
||||||
|
nt.registerObjects[i].registerObjectIndex = i;
|
||||||
|
EditorUtility.SetDirty(nt.registerObjects[i]);
|
||||||
|
}
|
||||||
|
EditorUtility.SetDirty(nt);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
|
@ -0,0 +1,25 @@
|
||||||
|
#if (UNITY_STANDALONE || UNITY_ANDROID || UNITY_IOS || UNITY_WSA || UNITY_WEBGL) && UNITY_EDITOR
|
||||||
|
using Net.UnityComponent;
|
||||||
|
using UnityEditor;
|
||||||
|
using UnityEngine;
|
||||||
|
|
||||||
|
[CustomEditor(typeof(NetworkTransform))]
|
||||||
|
[CanEditMultipleObjects]
|
||||||
|
public class NetworkTransformEdit : Editor
|
||||||
|
{
|
||||||
|
private NetworkTransform nt;
|
||||||
|
|
||||||
|
private void OnEnable()
|
||||||
|
{
|
||||||
|
nt = target as NetworkTransform;
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void OnInspectorGUI()
|
||||||
|
{
|
||||||
|
base.OnInspectorGUI();
|
||||||
|
GUI.enabled = false;
|
||||||
|
EditorGUILayout.LabelField("mode", nt.currMode.ToString());
|
||||||
|
GUI.enabled = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
|
@ -0,0 +1,49 @@
|
||||||
|
#if (UNITY_STANDALONE || UNITY_ANDROID || UNITY_IOS || UNITY_WSA || UNITY_WEBGL) && UNITY_EDITOR
|
||||||
|
using Net.UnityComponent;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using UnityEditor;
|
||||||
|
using UnityEngine;
|
||||||
|
|
||||||
|
[CustomEditor(typeof(NetworkTransformMulti))]
|
||||||
|
[CanEditMultipleObjects]
|
||||||
|
public class NetworkTransformMultiEdit : Editor
|
||||||
|
{
|
||||||
|
private NetworkTransformMulti nt;
|
||||||
|
|
||||||
|
private void OnEnable()
|
||||||
|
{
|
||||||
|
nt = target as NetworkTransformMulti;
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void OnInspectorGUI()
|
||||||
|
{
|
||||||
|
base.OnInspectorGUI();
|
||||||
|
GUI.enabled = false;
|
||||||
|
EditorGUILayout.LabelField("mode", nt.currMode.ToString());
|
||||||
|
GUI.enabled = true;
|
||||||
|
if (GUILayout.Button("更新子物体"))
|
||||||
|
{
|
||||||
|
var childs1 = nt.transform.GetComponentsInChildren<Transform>();
|
||||||
|
var list = new List<ChildTransform>();
|
||||||
|
foreach (var child in childs1)
|
||||||
|
{
|
||||||
|
if (child == nt.transform)
|
||||||
|
continue;
|
||||||
|
if (!child.gameObject.activeInHierarchy)
|
||||||
|
continue;
|
||||||
|
list.Add(new ChildTransform()
|
||||||
|
{
|
||||||
|
name = child.name,
|
||||||
|
transform = child,
|
||||||
|
mode = nt.syncMode,
|
||||||
|
syncPosition = nt.syncPosition,
|
||||||
|
syncRotation = nt.syncRotation,
|
||||||
|
syncScale = nt.syncScale,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
nt.childs = list.ToArray();
|
||||||
|
EditorUtility.SetDirty(nt);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
After Width: | Height: | Size: 3.5 KiB |
After Width: | Height: | Size: 4.0 KiB |
After Width: | Height: | Size: 3.3 KiB |
After Width: | Height: | Size: 4.0 KiB |
After Width: | Height: | Size: 2.7 KiB |
After Width: | Height: | Size: 4.9 KiB |
After Width: | Height: | Size: 5.5 KiB |
After Width: | Height: | Size: 1.5 KiB |
After Width: | Height: | Size: 3.6 KiB |
|
@ -0,0 +1,648 @@
|
||||||
|
#if UNITY_STANDALONE || UNITY_ANDROID || UNITY_IOS || UNITY_WSA || UNITY_WEBGL
|
||||||
|
using Net.Client;
|
||||||
|
using Net.Share;
|
||||||
|
using Net.Component;
|
||||||
|
using Net.UnityComponent;
|
||||||
|
using UnityEngine;
|
||||||
|
using Net.System;
|
||||||
|
using static Net.Serialize.NetConvertFast2;
|
||||||
|
|
||||||
|
namespace BuildComponent
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Animation同步组件, 此代码由BuildComponentTools工具生成, 如果同步发生相互影响的字段或属性, 请自行检查处理一下!
|
||||||
|
/// </summary>
|
||||||
|
[RequireComponent(typeof(UnityEngine.Animation))]
|
||||||
|
public class NetworkAnimation : NetworkBehaviour
|
||||||
|
{
|
||||||
|
private UnityEngine.Animation self;
|
||||||
|
public bool autoCheck;
|
||||||
|
private object[] fields;
|
||||||
|
private int[] eventsId;
|
||||||
|
|
||||||
|
public void Awake()
|
||||||
|
{
|
||||||
|
self = GetComponent<UnityEngine.Animation>();
|
||||||
|
fields = new object[40];
|
||||||
|
eventsId = new int[40];
|
||||||
|
fields[1] = self.clip;
|
||||||
|
fields[2] = self.playAutomatically;
|
||||||
|
fields[3] = self.wrapMode;
|
||||||
|
fields[4] = self.animatePhysics;
|
||||||
|
fields[5] = self.cullingType;
|
||||||
|
}
|
||||||
|
|
||||||
|
public UnityEngine.AnimationClip clip
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
return self.clip;
|
||||||
|
}
|
||||||
|
set
|
||||||
|
{
|
||||||
|
if (value.Equals(fields[1]))
|
||||||
|
return;
|
||||||
|
fields[1] = value;
|
||||||
|
self.clip = value;
|
||||||
|
ClientBase.Instance.AddOperation(new Operation(Command.BuildComponent, netObj.Identity)
|
||||||
|
{
|
||||||
|
index = netObj.registerObjectIndex,
|
||||||
|
index1 = NetComponentID,
|
||||||
|
index2 = 1,
|
||||||
|
buffer = SerializeObject(value).ToArray(true),
|
||||||
|
uid = ClientBase.Instance.UID
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
public System.Boolean playAutomatically
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
return self.playAutomatically;
|
||||||
|
}
|
||||||
|
set
|
||||||
|
{
|
||||||
|
if (value.Equals(fields[2]))
|
||||||
|
return;
|
||||||
|
fields[2] = value;
|
||||||
|
self.playAutomatically = value;
|
||||||
|
ClientBase.Instance.AddOperation(new Operation(Command.BuildComponent, netObj.Identity)
|
||||||
|
{
|
||||||
|
index = netObj.registerObjectIndex,
|
||||||
|
index1 = NetComponentID,
|
||||||
|
index2 = 2,
|
||||||
|
buffer = SerializeObject(value).ToArray(true),
|
||||||
|
uid = ClientBase.Instance.UID
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
public UnityEngine.WrapMode wrapMode
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
return self.wrapMode;
|
||||||
|
}
|
||||||
|
set
|
||||||
|
{
|
||||||
|
if (value.Equals(fields[3]))
|
||||||
|
return;
|
||||||
|
fields[3] = value;
|
||||||
|
self.wrapMode = value;
|
||||||
|
ClientBase.Instance.AddOperation(new Operation(Command.BuildComponent, netObj.Identity)
|
||||||
|
{
|
||||||
|
index = netObj.registerObjectIndex,
|
||||||
|
index1 = NetComponentID,
|
||||||
|
index2 = 3,
|
||||||
|
buffer = SerializeObject(value).ToArray(true),
|
||||||
|
uid = ClientBase.Instance.UID
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
public System.Boolean animatePhysics
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
return self.animatePhysics;
|
||||||
|
}
|
||||||
|
set
|
||||||
|
{
|
||||||
|
if (value.Equals(fields[4]))
|
||||||
|
return;
|
||||||
|
fields[4] = value;
|
||||||
|
self.animatePhysics = value;
|
||||||
|
ClientBase.Instance.AddOperation(new Operation(Command.BuildComponent, netObj.Identity)
|
||||||
|
{
|
||||||
|
index = netObj.registerObjectIndex,
|
||||||
|
index1 = NetComponentID,
|
||||||
|
index2 = 4,
|
||||||
|
buffer = SerializeObject(value).ToArray(true),
|
||||||
|
uid = ClientBase.Instance.UID
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
public UnityEngine.AnimationCullingType cullingType
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
return self.cullingType;
|
||||||
|
}
|
||||||
|
set
|
||||||
|
{
|
||||||
|
if (value.Equals(fields[5]))
|
||||||
|
return;
|
||||||
|
fields[5] = value;
|
||||||
|
self.cullingType = value;
|
||||||
|
ClientBase.Instance.AddOperation(new Operation(Command.BuildComponent, netObj.Identity)
|
||||||
|
{
|
||||||
|
index = netObj.registerObjectIndex,
|
||||||
|
index1 = NetComponentID,
|
||||||
|
index2 = 5,
|
||||||
|
buffer = SerializeObject(value).ToArray(true),
|
||||||
|
uid = ClientBase.Instance.UID
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
public override void OnPropertyAutoCheck()
|
||||||
|
{
|
||||||
|
if (!autoCheck)
|
||||||
|
return;
|
||||||
|
|
||||||
|
clip = clip;
|
||||||
|
playAutomatically = playAutomatically;
|
||||||
|
wrapMode = wrapMode;
|
||||||
|
animatePhysics = animatePhysics;
|
||||||
|
cullingType = cullingType;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Stop(System.String name, bool always = false, int executeNumber = 0, float time = 0)
|
||||||
|
{
|
||||||
|
if (name.Equals(fields[7]) & !always) return;
|
||||||
|
fields[7] = name;
|
||||||
|
var buffer = SerializeModel(new RPCModel() { pars = new object[] { name, } });
|
||||||
|
ClientBase.Instance.AddOperation(new Operation(Command.BuildComponent, netObj.Identity)
|
||||||
|
{
|
||||||
|
index = netObj.registerObjectIndex,
|
||||||
|
index1 = NetComponentID,
|
||||||
|
index2 = 6,
|
||||||
|
buffer = buffer
|
||||||
|
});
|
||||||
|
if (executeNumber > 0)
|
||||||
|
{
|
||||||
|
ThreadManager.Event.RemoveEvent(eventsId[6]);
|
||||||
|
eventsId[6] = ThreadManager.Event.AddEvent(time, executeNumber, (obj)=> {
|
||||||
|
Stop(name, true, 0, 0);
|
||||||
|
}, null);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
public void Rewind(System.String name, bool always = false, int executeNumber = 0, float time = 0)
|
||||||
|
{
|
||||||
|
if (name.Equals(fields[9]) & !always) return;
|
||||||
|
fields[9] = name;
|
||||||
|
var buffer = SerializeModel(new RPCModel() { pars = new object[] { name, } });
|
||||||
|
ClientBase.Instance.AddOperation(new Operation(Command.BuildComponent, netObj.Identity)
|
||||||
|
{
|
||||||
|
index = netObj.registerObjectIndex,
|
||||||
|
index1 = NetComponentID,
|
||||||
|
index2 = 8,
|
||||||
|
buffer = buffer
|
||||||
|
});
|
||||||
|
if (executeNumber > 0)
|
||||||
|
{
|
||||||
|
ThreadManager.Event.RemoveEvent(eventsId[8]);
|
||||||
|
eventsId[8] = ThreadManager.Event.AddEvent(time, executeNumber, (obj)=> {
|
||||||
|
Rewind(name, true, 0, 0);
|
||||||
|
}, null);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
public void Play( bool always = false, int executeNumber = 0, float time = 0)
|
||||||
|
{
|
||||||
|
if ( !always) return;
|
||||||
|
|
||||||
|
var buffer = SerializeModel(new RPCModel() { pars = new object[] { } });
|
||||||
|
ClientBase.Instance.AddOperation(new Operation(Command.BuildComponent, netObj.Identity)
|
||||||
|
{
|
||||||
|
index = netObj.registerObjectIndex,
|
||||||
|
index1 = NetComponentID,
|
||||||
|
index2 = 10,
|
||||||
|
buffer = buffer
|
||||||
|
});
|
||||||
|
if (executeNumber > 0)
|
||||||
|
{
|
||||||
|
ThreadManager.Event.RemoveEvent(eventsId[10]);
|
||||||
|
eventsId[10] = ThreadManager.Event.AddEvent(time, executeNumber, (obj)=> {
|
||||||
|
Play( true, 0, 0);
|
||||||
|
}, null);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
public void Play(UnityEngine.PlayMode mode, bool always = false, int executeNumber = 0, float time = 0)
|
||||||
|
{
|
||||||
|
if (mode.Equals(fields[12]) & !always) return;
|
||||||
|
fields[12] = mode;
|
||||||
|
var buffer = SerializeModel(new RPCModel() { pars = new object[] { mode, } });
|
||||||
|
ClientBase.Instance.AddOperation(new Operation(Command.BuildComponent, netObj.Identity)
|
||||||
|
{
|
||||||
|
index = netObj.registerObjectIndex,
|
||||||
|
index1 = NetComponentID,
|
||||||
|
index2 = 11,
|
||||||
|
buffer = buffer
|
||||||
|
});
|
||||||
|
if (executeNumber > 0)
|
||||||
|
{
|
||||||
|
ThreadManager.Event.RemoveEvent(eventsId[11]);
|
||||||
|
eventsId[11] = ThreadManager.Event.AddEvent(time, executeNumber, (obj)=> {
|
||||||
|
Play(mode, true, 0, 0);
|
||||||
|
}, null);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
public void Play(System.String animation, bool always = false, int executeNumber = 0, float time = 0)
|
||||||
|
{
|
||||||
|
if (animation.Equals(fields[14]) & !always) return;
|
||||||
|
fields[14] = animation;
|
||||||
|
var buffer = SerializeModel(new RPCModel() { pars = new object[] { animation, } });
|
||||||
|
ClientBase.Instance.AddOperation(new Operation(Command.BuildComponent, netObj.Identity)
|
||||||
|
{
|
||||||
|
index = netObj.registerObjectIndex,
|
||||||
|
index1 = NetComponentID,
|
||||||
|
index2 = 13,
|
||||||
|
buffer = buffer
|
||||||
|
});
|
||||||
|
if (executeNumber > 0)
|
||||||
|
{
|
||||||
|
ThreadManager.Event.RemoveEvent(eventsId[13]);
|
||||||
|
eventsId[13] = ThreadManager.Event.AddEvent(time, executeNumber, (obj)=> {
|
||||||
|
Play(animation, true, 0, 0);
|
||||||
|
}, null);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
public void CrossFade(System.String animation, bool always = false, int executeNumber = 0, float time = 0)
|
||||||
|
{
|
||||||
|
if (animation.Equals(fields[16]) & !always) return;
|
||||||
|
fields[16] = animation;
|
||||||
|
var buffer = SerializeModel(new RPCModel() { pars = new object[] { animation, } });
|
||||||
|
ClientBase.Instance.AddOperation(new Operation(Command.BuildComponent, netObj.Identity)
|
||||||
|
{
|
||||||
|
index = netObj.registerObjectIndex,
|
||||||
|
index1 = NetComponentID,
|
||||||
|
index2 = 15,
|
||||||
|
buffer = buffer
|
||||||
|
});
|
||||||
|
if (executeNumber > 0)
|
||||||
|
{
|
||||||
|
ThreadManager.Event.RemoveEvent(eventsId[15]);
|
||||||
|
eventsId[15] = ThreadManager.Event.AddEvent(time, executeNumber, (obj)=> {
|
||||||
|
CrossFade(animation, true, 0, 0);
|
||||||
|
}, null);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
public void CrossFade(System.String animation,System.Single fadeLength, bool always = false, int executeNumber = 0, float time = 0)
|
||||||
|
{
|
||||||
|
if (animation.Equals(fields[18]) & fadeLength.Equals(fields[19]) & !always) return;
|
||||||
|
fields[18] = animation;
|
||||||
|
fields[19] = fadeLength;
|
||||||
|
var buffer = SerializeModel(new RPCModel() { pars = new object[] { animation,fadeLength, } });
|
||||||
|
ClientBase.Instance.AddOperation(new Operation(Command.BuildComponent, netObj.Identity)
|
||||||
|
{
|
||||||
|
index = netObj.registerObjectIndex,
|
||||||
|
index1 = NetComponentID,
|
||||||
|
index2 = 17,
|
||||||
|
buffer = buffer
|
||||||
|
});
|
||||||
|
if (executeNumber > 0)
|
||||||
|
{
|
||||||
|
ThreadManager.Event.RemoveEvent(eventsId[17]);
|
||||||
|
eventsId[17] = ThreadManager.Event.AddEvent(time, executeNumber, (obj)=> {
|
||||||
|
CrossFade(animation,fadeLength, true, 0, 0);
|
||||||
|
}, null);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
public void Blend(System.String animation, bool always = false, int executeNumber = 0, float time = 0)
|
||||||
|
{
|
||||||
|
if (animation.Equals(fields[21]) & !always) return;
|
||||||
|
fields[21] = animation;
|
||||||
|
var buffer = SerializeModel(new RPCModel() { pars = new object[] { animation, } });
|
||||||
|
ClientBase.Instance.AddOperation(new Operation(Command.BuildComponent, netObj.Identity)
|
||||||
|
{
|
||||||
|
index = netObj.registerObjectIndex,
|
||||||
|
index1 = NetComponentID,
|
||||||
|
index2 = 20,
|
||||||
|
buffer = buffer
|
||||||
|
});
|
||||||
|
if (executeNumber > 0)
|
||||||
|
{
|
||||||
|
ThreadManager.Event.RemoveEvent(eventsId[20]);
|
||||||
|
eventsId[20] = ThreadManager.Event.AddEvent(time, executeNumber, (obj)=> {
|
||||||
|
Blend(animation, true, 0, 0);
|
||||||
|
}, null);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
public void Blend(System.String animation,System.Single targetWeight, bool always = false, int executeNumber = 0, float time = 0)
|
||||||
|
{
|
||||||
|
if (animation.Equals(fields[23]) & targetWeight.Equals(fields[24]) & !always) return;
|
||||||
|
fields[23] = animation;
|
||||||
|
fields[24] = targetWeight;
|
||||||
|
var buffer = SerializeModel(new RPCModel() { pars = new object[] { animation,targetWeight, } });
|
||||||
|
ClientBase.Instance.AddOperation(new Operation(Command.BuildComponent, netObj.Identity)
|
||||||
|
{
|
||||||
|
index = netObj.registerObjectIndex,
|
||||||
|
index1 = NetComponentID,
|
||||||
|
index2 = 22,
|
||||||
|
buffer = buffer
|
||||||
|
});
|
||||||
|
if (executeNumber > 0)
|
||||||
|
{
|
||||||
|
ThreadManager.Event.RemoveEvent(eventsId[22]);
|
||||||
|
eventsId[22] = ThreadManager.Event.AddEvent(time, executeNumber, (obj)=> {
|
||||||
|
Blend(animation,targetWeight, true, 0, 0);
|
||||||
|
}, null);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
public void CrossFadeQueued(System.String animation, bool always = false, int executeNumber = 0, float time = 0)
|
||||||
|
{
|
||||||
|
if (animation.Equals(fields[26]) & !always) return;
|
||||||
|
fields[26] = animation;
|
||||||
|
var buffer = SerializeModel(new RPCModel() { pars = new object[] { animation, } });
|
||||||
|
ClientBase.Instance.AddOperation(new Operation(Command.BuildComponent, netObj.Identity)
|
||||||
|
{
|
||||||
|
index = netObj.registerObjectIndex,
|
||||||
|
index1 = NetComponentID,
|
||||||
|
index2 = 25,
|
||||||
|
buffer = buffer
|
||||||
|
});
|
||||||
|
if (executeNumber > 0)
|
||||||
|
{
|
||||||
|
ThreadManager.Event.RemoveEvent(eventsId[25]);
|
||||||
|
eventsId[25] = ThreadManager.Event.AddEvent(time, executeNumber, (obj)=> {
|
||||||
|
CrossFadeQueued(animation, true, 0, 0);
|
||||||
|
}, null);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
public void CrossFadeQueued(System.String animation,System.Single fadeLength, bool always = false, int executeNumber = 0, float time = 0)
|
||||||
|
{
|
||||||
|
if (animation.Equals(fields[28]) & fadeLength.Equals(fields[29]) & !always) return;
|
||||||
|
fields[28] = animation;
|
||||||
|
fields[29] = fadeLength;
|
||||||
|
var buffer = SerializeModel(new RPCModel() { pars = new object[] { animation,fadeLength, } });
|
||||||
|
ClientBase.Instance.AddOperation(new Operation(Command.BuildComponent, netObj.Identity)
|
||||||
|
{
|
||||||
|
index = netObj.registerObjectIndex,
|
||||||
|
index1 = NetComponentID,
|
||||||
|
index2 = 27,
|
||||||
|
buffer = buffer
|
||||||
|
});
|
||||||
|
if (executeNumber > 0)
|
||||||
|
{
|
||||||
|
ThreadManager.Event.RemoveEvent(eventsId[27]);
|
||||||
|
eventsId[27] = ThreadManager.Event.AddEvent(time, executeNumber, (obj)=> {
|
||||||
|
CrossFadeQueued(animation,fadeLength, true, 0, 0);
|
||||||
|
}, null);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
public void CrossFadeQueued(System.String animation,System.Single fadeLength,UnityEngine.QueueMode queue, bool always = false, int executeNumber = 0, float time = 0)
|
||||||
|
{
|
||||||
|
if (animation.Equals(fields[31]) & fadeLength.Equals(fields[32]) & queue.Equals(fields[33]) & !always) return;
|
||||||
|
fields[31] = animation;
|
||||||
|
fields[32] = fadeLength;
|
||||||
|
fields[33] = queue;
|
||||||
|
var buffer = SerializeModel(new RPCModel() { pars = new object[] { animation,fadeLength,queue, } });
|
||||||
|
ClientBase.Instance.AddOperation(new Operation(Command.BuildComponent, netObj.Identity)
|
||||||
|
{
|
||||||
|
index = netObj.registerObjectIndex,
|
||||||
|
index1 = NetComponentID,
|
||||||
|
index2 = 30,
|
||||||
|
buffer = buffer
|
||||||
|
});
|
||||||
|
if (executeNumber > 0)
|
||||||
|
{
|
||||||
|
ThreadManager.Event.RemoveEvent(eventsId[30]);
|
||||||
|
eventsId[30] = ThreadManager.Event.AddEvent(time, executeNumber, (obj)=> {
|
||||||
|
CrossFadeQueued(animation,fadeLength,queue, true, 0, 0);
|
||||||
|
}, null);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
public void PlayQueued(System.String animation, bool always = false, int executeNumber = 0, float time = 0)
|
||||||
|
{
|
||||||
|
if (animation.Equals(fields[35]) & !always) return;
|
||||||
|
fields[35] = animation;
|
||||||
|
var buffer = SerializeModel(new RPCModel() { pars = new object[] { animation, } });
|
||||||
|
ClientBase.Instance.AddOperation(new Operation(Command.BuildComponent, netObj.Identity)
|
||||||
|
{
|
||||||
|
index = netObj.registerObjectIndex,
|
||||||
|
index1 = NetComponentID,
|
||||||
|
index2 = 34,
|
||||||
|
buffer = buffer
|
||||||
|
});
|
||||||
|
if (executeNumber > 0)
|
||||||
|
{
|
||||||
|
ThreadManager.Event.RemoveEvent(eventsId[34]);
|
||||||
|
eventsId[34] = ThreadManager.Event.AddEvent(time, executeNumber, (obj)=> {
|
||||||
|
PlayQueued(animation, true, 0, 0);
|
||||||
|
}, null);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
public void PlayQueued(System.String animation,UnityEngine.QueueMode queue, bool always = false, int executeNumber = 0, float time = 0)
|
||||||
|
{
|
||||||
|
if (animation.Equals(fields[37]) & queue.Equals(fields[38]) & !always) return;
|
||||||
|
fields[37] = animation;
|
||||||
|
fields[38] = queue;
|
||||||
|
var buffer = SerializeModel(new RPCModel() { pars = new object[] { animation,queue, } });
|
||||||
|
ClientBase.Instance.AddOperation(new Operation(Command.BuildComponent, netObj.Identity)
|
||||||
|
{
|
||||||
|
index = netObj.registerObjectIndex,
|
||||||
|
index1 = NetComponentID,
|
||||||
|
index2 = 36,
|
||||||
|
buffer = buffer
|
||||||
|
});
|
||||||
|
if (executeNumber > 0)
|
||||||
|
{
|
||||||
|
ThreadManager.Event.RemoveEvent(eventsId[36]);
|
||||||
|
eventsId[36] = ThreadManager.Event.AddEvent(time, executeNumber, (obj)=> {
|
||||||
|
PlayQueued(animation,queue, true, 0, 0);
|
||||||
|
}, null);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
public void RemoveClip(System.String clipName, bool always = false, int executeNumber = 0, float time = 0)
|
||||||
|
{
|
||||||
|
if (clipName.Equals(fields[40]) & !always) return;
|
||||||
|
fields[40] = clipName;
|
||||||
|
var buffer = SerializeModel(new RPCModel() { pars = new object[] { clipName, } });
|
||||||
|
ClientBase.Instance.AddOperation(new Operation(Command.BuildComponent, netObj.Identity)
|
||||||
|
{
|
||||||
|
index = netObj.registerObjectIndex,
|
||||||
|
index1 = NetComponentID,
|
||||||
|
index2 = 39,
|
||||||
|
buffer = buffer
|
||||||
|
});
|
||||||
|
if (executeNumber > 0)
|
||||||
|
{
|
||||||
|
ThreadManager.Event.RemoveEvent(eventsId[39]);
|
||||||
|
eventsId[39] = ThreadManager.Event.AddEvent(time, executeNumber, (obj)=> {
|
||||||
|
RemoveClip(clipName, true, 0, 0);
|
||||||
|
}, null);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
public System.Collections.IEnumerator GetEnumerator()
|
||||||
|
{
|
||||||
|
return self.GetEnumerator();
|
||||||
|
}
|
||||||
|
public UnityEngine.AnimationClip GetClip(System.String name)
|
||||||
|
{
|
||||||
|
return self.GetClip(name);
|
||||||
|
}
|
||||||
|
public override void OnNetworkOperationHandler(Operation opt)
|
||||||
|
{
|
||||||
|
switch (opt.index2)
|
||||||
|
{
|
||||||
|
|
||||||
|
case 1:
|
||||||
|
{
|
||||||
|
if (opt.uid == ClientBase.Instance.UID)
|
||||||
|
return;
|
||||||
|
var clip = DeserializeObject<UnityEngine.AnimationClip>(new Segment(opt.buffer, false));
|
||||||
|
fields[1] = clip;
|
||||||
|
self.clip = clip;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case 2:
|
||||||
|
{
|
||||||
|
if (opt.uid == ClientBase.Instance.UID)
|
||||||
|
return;
|
||||||
|
var playAutomatically = DeserializeObject<System.Boolean>(new Segment(opt.buffer, false));
|
||||||
|
fields[2] = playAutomatically;
|
||||||
|
self.playAutomatically = playAutomatically;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case 3:
|
||||||
|
{
|
||||||
|
if (opt.uid == ClientBase.Instance.UID)
|
||||||
|
return;
|
||||||
|
var wrapMode = DeserializeObject<UnityEngine.WrapMode>(new Segment(opt.buffer, false));
|
||||||
|
fields[3] = wrapMode;
|
||||||
|
self.wrapMode = wrapMode;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case 4:
|
||||||
|
{
|
||||||
|
if (opt.uid == ClientBase.Instance.UID)
|
||||||
|
return;
|
||||||
|
var animatePhysics = DeserializeObject<System.Boolean>(new Segment(opt.buffer, false));
|
||||||
|
fields[4] = animatePhysics;
|
||||||
|
self.animatePhysics = animatePhysics;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case 5:
|
||||||
|
{
|
||||||
|
if (opt.uid == ClientBase.Instance.UID)
|
||||||
|
return;
|
||||||
|
var cullingType = DeserializeObject<UnityEngine.AnimationCullingType>(new Segment(opt.buffer, false));
|
||||||
|
fields[5] = cullingType;
|
||||||
|
self.cullingType = cullingType;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case 6:
|
||||||
|
{
|
||||||
|
var segment = new Segment(opt.buffer, false);
|
||||||
|
var data = DeserializeModel(segment);
|
||||||
|
var name = (System.String)(fields[7] = data.Obj);
|
||||||
|
self.Stop(name);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case 8:
|
||||||
|
{
|
||||||
|
var segment = new Segment(opt.buffer, false);
|
||||||
|
var data = DeserializeModel(segment);
|
||||||
|
var name = (System.String)(fields[9] = data.Obj);
|
||||||
|
self.Rewind(name);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case 10:
|
||||||
|
{
|
||||||
|
self.Play();
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case 11:
|
||||||
|
{
|
||||||
|
var segment = new Segment(opt.buffer, false);
|
||||||
|
var data = DeserializeModel(segment);
|
||||||
|
var mode = (UnityEngine.PlayMode)(fields[12] = data.Obj);
|
||||||
|
self.Play(mode);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case 13:
|
||||||
|
{
|
||||||
|
var segment = new Segment(opt.buffer, false);
|
||||||
|
var data = DeserializeModel(segment);
|
||||||
|
var animation = (System.String)(fields[14] = data.Obj);
|
||||||
|
self.Play(animation);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case 15:
|
||||||
|
{
|
||||||
|
var segment = new Segment(opt.buffer, false);
|
||||||
|
var data = DeserializeModel(segment);
|
||||||
|
var animation = (System.String)(fields[16] = data.Obj);
|
||||||
|
self.CrossFade(animation);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case 17:
|
||||||
|
{
|
||||||
|
var segment = new Segment(opt.buffer, false);
|
||||||
|
var data = DeserializeModel(segment);
|
||||||
|
var animation = (System.String)(fields[18] = data.Obj);
|
||||||
|
var fadeLength = (System.Single)(fields[19] = data.Obj);
|
||||||
|
self.CrossFade(animation,fadeLength);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case 20:
|
||||||
|
{
|
||||||
|
var segment = new Segment(opt.buffer, false);
|
||||||
|
var data = DeserializeModel(segment);
|
||||||
|
var animation = (System.String)(fields[21] = data.Obj);
|
||||||
|
self.Blend(animation);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case 22:
|
||||||
|
{
|
||||||
|
var segment = new Segment(opt.buffer, false);
|
||||||
|
var data = DeserializeModel(segment);
|
||||||
|
var animation = (System.String)(fields[23] = data.Obj);
|
||||||
|
var targetWeight = (System.Single)(fields[24] = data.Obj);
|
||||||
|
self.Blend(animation,targetWeight);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case 25:
|
||||||
|
{
|
||||||
|
var segment = new Segment(opt.buffer, false);
|
||||||
|
var data = DeserializeModel(segment);
|
||||||
|
var animation = (System.String)(fields[26] = data.Obj);
|
||||||
|
self.CrossFadeQueued(animation);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case 27:
|
||||||
|
{
|
||||||
|
var segment = new Segment(opt.buffer, false);
|
||||||
|
var data = DeserializeModel(segment);
|
||||||
|
var animation = (System.String)(fields[28] = data.Obj);
|
||||||
|
var fadeLength = (System.Single)(fields[29] = data.Obj);
|
||||||
|
self.CrossFadeQueued(animation,fadeLength);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case 30:
|
||||||
|
{
|
||||||
|
var segment = new Segment(opt.buffer, false);
|
||||||
|
var data = DeserializeModel(segment);
|
||||||
|
var animation = (System.String)(fields[31] = data.Obj);
|
||||||
|
var fadeLength = (System.Single)(fields[32] = data.Obj);
|
||||||
|
var queue = (UnityEngine.QueueMode)(fields[33] = data.Obj);
|
||||||
|
self.CrossFadeQueued(animation,fadeLength,queue);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case 34:
|
||||||
|
{
|
||||||
|
var segment = new Segment(opt.buffer, false);
|
||||||
|
var data = DeserializeModel(segment);
|
||||||
|
var animation = (System.String)(fields[35] = data.Obj);
|
||||||
|
self.PlayQueued(animation);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case 36:
|
||||||
|
{
|
||||||
|
var segment = new Segment(opt.buffer, false);
|
||||||
|
var data = DeserializeModel(segment);
|
||||||
|
var animation = (System.String)(fields[37] = data.Obj);
|
||||||
|
var queue = (UnityEngine.QueueMode)(fields[38] = data.Obj);
|
||||||
|
self.PlayQueued(animation,queue);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case 39:
|
||||||
|
{
|
||||||
|
var segment = new Segment(opt.buffer, false);
|
||||||
|
var data = DeserializeModel(segment);
|
||||||
|
var clipName = (System.String)(fields[40] = data.Obj);
|
||||||
|
self.RemoveClip(clipName);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
|
@ -0,0 +1,360 @@
|
||||||
|
#if UNITY_STANDALONE || UNITY_ANDROID || UNITY_IOS || UNITY_WSA || UNITY_WEBGL
|
||||||
|
namespace Net.Component
|
||||||
|
{
|
||||||
|
using Net.Client;
|
||||||
|
using Net.Event;
|
||||||
|
using Net.Share;
|
||||||
|
using global::System;
|
||||||
|
using global::System.Threading;
|
||||||
|
using UnityEngine;
|
||||||
|
using global::System.Net;
|
||||||
|
using Net.Helper;
|
||||||
|
using Cysharp.Threading.Tasks;
|
||||||
|
|
||||||
|
public enum TransportProtocol
|
||||||
|
{
|
||||||
|
Tcp, Gcp, Udx, Kcp, Web
|
||||||
|
}
|
||||||
|
|
||||||
|
public enum LogMode
|
||||||
|
{
|
||||||
|
None,
|
||||||
|
/// <summary>
|
||||||
|
/// 消息输出, 警告输出, 错误输出, 三种模式各自输出
|
||||||
|
/// </summary>
|
||||||
|
Default,
|
||||||
|
/// <summary>
|
||||||
|
/// 所有消息输出都以白色消息输出
|
||||||
|
/// </summary>
|
||||||
|
LogAll,
|
||||||
|
/// <summary>
|
||||||
|
/// 警告信息和消息一起输出为白色
|
||||||
|
/// </summary>
|
||||||
|
LogAndWarning,
|
||||||
|
/// <summary>
|
||||||
|
/// 警告和错误都输出为红色提示
|
||||||
|
/// </summary>
|
||||||
|
WarnAndError,
|
||||||
|
/// <summary>
|
||||||
|
/// 只输出错误日志
|
||||||
|
/// </summary>
|
||||||
|
OnlyError,
|
||||||
|
/// <summary>
|
||||||
|
/// 只输入警告和错误日志
|
||||||
|
/// </summary>
|
||||||
|
OnlyWarnAndError,
|
||||||
|
}
|
||||||
|
|
||||||
|
[DefaultExecutionOrder(1)]//在NetworkTransform组件之前执行OnDestroy,控制NetworkTransform处于Control模式时退出游戏会同步删除所有网络物体
|
||||||
|
public class ClientManager : SingleCase<ClientManager>, ISendHandle
|
||||||
|
{
|
||||||
|
private bool mainInstance;
|
||||||
|
private ClientBase _client;
|
||||||
|
public TransportProtocol protocol = TransportProtocol.Tcp;
|
||||||
|
public string ip = "127.0.0.1";
|
||||||
|
public int port = 9543;
|
||||||
|
#if UNITY_EDITOR
|
||||||
|
public bool localTest;
|
||||||
|
#endif
|
||||||
|
public LogMode logMode = LogMode.Default;
|
||||||
|
public bool debugRpc = true;
|
||||||
|
public bool authorize;
|
||||||
|
public bool startConnect = true;
|
||||||
|
public bool md5CRC;
|
||||||
|
public int reconnectCount = 10;
|
||||||
|
public int reconnectInterval = 2000;
|
||||||
|
public byte heartLimit = 5;
|
||||||
|
public int heartInterval = 1000;
|
||||||
|
public bool dontDestroyOnLoad = true;
|
||||||
|
|
||||||
|
#pragma warning disable IDE1006 // 命名样式
|
||||||
|
public ClientBase client
|
||||||
|
#pragma warning restore IDE1006 // 命名样式
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
if (_client == null)
|
||||||
|
{
|
||||||
|
var typeName = $"Net.Client.{protocol}Client";
|
||||||
|
var type = AssemblyHelper.GetType(typeName);
|
||||||
|
if (type == null)
|
||||||
|
throw new Exception($"请导入:{protocol}协议!!!");
|
||||||
|
_client = Activator.CreateInstance(type, new object[] { true }) as ClientBase;
|
||||||
|
_client.host = ip;
|
||||||
|
_client.port = port;
|
||||||
|
_client.LogRpc = debugRpc;
|
||||||
|
_client.MD5CRC = md5CRC;
|
||||||
|
_client.ReconnectCount = reconnectCount;
|
||||||
|
_client.ReconnectInterval = reconnectInterval;
|
||||||
|
_client.SetHeartTime(heartLimit, heartInterval);
|
||||||
|
}
|
||||||
|
return _client;
|
||||||
|
}
|
||||||
|
set { _client = value; }
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 客户端唯一标识
|
||||||
|
/// </summary>
|
||||||
|
public static string Identify { get { return Instance.client.Identify; } }
|
||||||
|
/// <summary>
|
||||||
|
/// 客户端唯一标识
|
||||||
|
/// </summary>
|
||||||
|
public static int UID { get { return Instance.client.UID; } }
|
||||||
|
|
||||||
|
protected override void Awake()
|
||||||
|
{
|
||||||
|
base.Awake();
|
||||||
|
mainInstance = true;
|
||||||
|
if (dontDestroyOnLoad) DontDestroyOnLoad(gameObject);
|
||||||
|
Application.runInBackground = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Use this for initialization
|
||||||
|
void Start()
|
||||||
|
{
|
||||||
|
switch (logMode)
|
||||||
|
{
|
||||||
|
case LogMode.Default:
|
||||||
|
NDebug.BindLogAll(Debug.Log, Debug.LogWarning, Debug.LogError);
|
||||||
|
break;
|
||||||
|
case LogMode.LogAll:
|
||||||
|
NDebug.BindLogAll(Debug.Log);
|
||||||
|
break;
|
||||||
|
case LogMode.LogAndWarning:
|
||||||
|
NDebug.BindLogAll(Debug.Log, Debug.Log, Debug.LogError);
|
||||||
|
break;
|
||||||
|
case LogMode.WarnAndError:
|
||||||
|
NDebug.BindLogAll(Debug.Log, Debug.LogError, Debug.LogError);
|
||||||
|
break;
|
||||||
|
case LogMode.OnlyError:
|
||||||
|
NDebug.BindLogAll(null, null, Debug.LogError);
|
||||||
|
break;
|
||||||
|
case LogMode.OnlyWarnAndError:
|
||||||
|
NDebug.BindLogAll(null, Debug.LogError, Debug.LogError);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (startConnect)
|
||||||
|
Connect();
|
||||||
|
}
|
||||||
|
|
||||||
|
public UniTask<bool> Connect()
|
||||||
|
{
|
||||||
|
_client = client;
|
||||||
|
var ips = Dns.GetHostAddresses(ip);
|
||||||
|
if (ips.Length > 0)
|
||||||
|
_client.host = ips[RandomHelper.Range(0, ips.Length)].ToString();
|
||||||
|
else
|
||||||
|
_client.host = ip;
|
||||||
|
#if UNITY_EDITOR
|
||||||
|
if (localTest) _client.host = "127.0.0.1";
|
||||||
|
#endif
|
||||||
|
_client.port = port;
|
||||||
|
_client.AddRpcHandle(this);
|
||||||
|
return _client.Connect(result =>
|
||||||
|
{
|
||||||
|
if (result)
|
||||||
|
{
|
||||||
|
_client.Send(new byte[1]);//发送一个字节:调用服务器的OnUnClientRequest方法, 如果不需要账号登录, 则会直接允许进入服务器
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
// Update is called once per frame
|
||||||
|
void Update()
|
||||||
|
{
|
||||||
|
if (_client == null)
|
||||||
|
return;
|
||||||
|
_client.NetworkTick();
|
||||||
|
}
|
||||||
|
|
||||||
|
void OnDestroy()
|
||||||
|
{
|
||||||
|
if (!mainInstance)
|
||||||
|
return;
|
||||||
|
_client?.Close();
|
||||||
|
switch (logMode)
|
||||||
|
{
|
||||||
|
case LogMode.Default:
|
||||||
|
NDebug.RemoveLogAll(Debug.Log, Debug.LogWarning, Debug.LogError);
|
||||||
|
break;
|
||||||
|
case LogMode.LogAll:
|
||||||
|
NDebug.RemoveLogAll(Debug.Log);
|
||||||
|
break;
|
||||||
|
case LogMode.LogAndWarning:
|
||||||
|
NDebug.RemoveLogAll(Debug.Log, Debug.Log, Debug.LogError);
|
||||||
|
break;
|
||||||
|
case LogMode.WarnAndError:
|
||||||
|
NDebug.RemoveLogAll(Debug.Log, Debug.LogError, Debug.LogError);
|
||||||
|
break;
|
||||||
|
case LogMode.OnlyError:
|
||||||
|
NDebug.RemoveLogAll(null, null, Debug.LogError);
|
||||||
|
break;
|
||||||
|
case LogMode.OnlyWarnAndError:
|
||||||
|
NDebug.RemoveLogAll(null, Debug.LogError, Debug.LogError);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 发起场景同步操作, 在同一个场景的所有客户端都会收到该操作参数operation
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="operation"></param>
|
||||||
|
public static void AddOperation(Operation operation)
|
||||||
|
{
|
||||||
|
Instance.client.AddOperation(operation);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void AddRpc(object target)
|
||||||
|
{
|
||||||
|
I.client.AddRpcHandle(target);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void RemoveRpc(object target)
|
||||||
|
{
|
||||||
|
I.client.RemoveRpc(target);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 判断name是否是本地唯一id(本机玩家标识)
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="name"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
internal static bool IsLocal(string name)
|
||||||
|
{
|
||||||
|
if (Instance == null)
|
||||||
|
return false;
|
||||||
|
return instance._client.Identify == name;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 判断uid是否是本地唯一id(本机玩家标识)
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="uid"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
internal static bool IsLocal(int uid)
|
||||||
|
{
|
||||||
|
if (Instance == null)
|
||||||
|
return false;
|
||||||
|
return instance._client.UID == uid;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void CallUnity(Action ptr)
|
||||||
|
{
|
||||||
|
I.client.WorkerQueue.Enqueue(ptr);
|
||||||
|
}
|
||||||
|
|
||||||
|
#region 发送接口实现
|
||||||
|
public void Send(byte[] buffer)
|
||||||
|
{
|
||||||
|
((ISendHandle)_client).Send(buffer);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Send(byte cmd, byte[] buffer)
|
||||||
|
{
|
||||||
|
((ISendHandle)_client).Send(cmd, buffer);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Send(string func, params object[] pars)
|
||||||
|
{
|
||||||
|
((ISendHandle)_client).Send(func, pars);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Send(byte cmd, string func, params object[] pars)
|
||||||
|
{
|
||||||
|
((ISendHandle)_client).Send(cmd, func, pars);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void CallRpc(string func, params object[] pars)
|
||||||
|
{
|
||||||
|
((ISendHandle)_client).CallRpc(func, pars);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void CallRpc(byte cmd, string func, params object[] pars)
|
||||||
|
{
|
||||||
|
((ISendHandle)_client).CallRpc(cmd, func, pars);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Request(string func, params object[] pars)
|
||||||
|
{
|
||||||
|
((ISendHandle)_client).Request(func, pars);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Request(byte cmd, string func, params object[] pars)
|
||||||
|
{
|
||||||
|
((ISendHandle)_client).Request(cmd, func, pars);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void SendRT(string func, params object[] pars)
|
||||||
|
{
|
||||||
|
((ISendHandle)_client).SendRT(func, pars);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void SendRT(byte cmd, string func, params object[] pars)
|
||||||
|
{
|
||||||
|
((ISendHandle)_client).SendRT(cmd, func, pars);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void SendRT(byte[] buffer)
|
||||||
|
{
|
||||||
|
((ISendHandle)_client).SendRT(buffer);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void SendRT(byte cmd, byte[] buffer)
|
||||||
|
{
|
||||||
|
((ISendHandle)_client).SendRT(cmd, buffer);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Send(string func, string funcCB, Delegate callback, params object[] pars)
|
||||||
|
{
|
||||||
|
((ISendHandle)_client).Send(func, funcCB, callback, pars);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Send(string func, string funcCB, Delegate callback, int millisecondsDelay, params object[] pars)
|
||||||
|
{
|
||||||
|
((ISendHandle)_client).Send(func, funcCB, callback, millisecondsDelay, pars);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Send(string func, string funcCB, Delegate callback, int millisecondsDelay, Action outTimeAct, params object[] pars)
|
||||||
|
{
|
||||||
|
((ISendHandle)_client).Send(func, funcCB, callback, millisecondsDelay, outTimeAct, pars);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Send(byte cmd, string func, string funcCB, Delegate callback, int millisecondsDelay, Action outTimeAct, params object[] pars)
|
||||||
|
{
|
||||||
|
((ISendHandle)_client).Send(cmd, func, funcCB, callback, millisecondsDelay, outTimeAct, pars);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void SendRT(string func, string funcCB, Delegate callback, params object[] pars)
|
||||||
|
{
|
||||||
|
((ISendHandle)_client).SendRT(func, funcCB, callback, pars);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void SendRT(string func, string funcCB, Delegate callback, int millisecondsDelay, params object[] pars)
|
||||||
|
{
|
||||||
|
((ISendHandle)_client).SendRT(func, funcCB, callback, millisecondsDelay, pars);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void SendRT(string func, string funcCB, Delegate callback, int millisecondsDelay, Action outTimeAct, params object[] pars)
|
||||||
|
{
|
||||||
|
((ISendHandle)_client).SendRT(func, funcCB, callback, millisecondsDelay, outTimeAct, pars);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void SendRT(byte cmd, string func, string funcCB, Delegate callback, int millisecondsDelay, Action outTimeAct, params object[] pars)
|
||||||
|
{
|
||||||
|
((ISendHandle)_client).SendRT(cmd, func, funcCB, callback, millisecondsDelay, outTimeAct, pars);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Send(byte cmd, string func, string funcCB, Delegate callback, int millisecondsDelay, Action outTimeAct, SynchronizationContext context, params object[] pars)
|
||||||
|
{
|
||||||
|
((ISendHandle)_client).Send(cmd, func, funcCB, callback, millisecondsDelay, outTimeAct, context, pars);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void SendRT(byte cmd, string func, string funcCB, Delegate callback, int millisecondsDelay, Action outTimeAct, SynchronizationContext context, params object[] pars)
|
||||||
|
{
|
||||||
|
((ISendHandle)_client).SendRT(cmd, func, funcCB, callback, millisecondsDelay, outTimeAct, context, pars);
|
||||||
|
}
|
||||||
|
#endregion
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
|
@ -0,0 +1,36 @@
|
||||||
|
#if UNITY_STANDALONE || UNITY_ANDROID || UNITY_IOS || UNITY_WSA || UNITY_WEBGL
|
||||||
|
namespace Net.Component
|
||||||
|
{
|
||||||
|
using UnityEngine;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 网络时间中心控制, 控制发送频率, 不能乱来发送! 一个行为一秒可以发送30次同步
|
||||||
|
/// </summary>
|
||||||
|
public class NetworkTime : SingleCase<NetworkTime>
|
||||||
|
{
|
||||||
|
private float time;
|
||||||
|
private static bool canSent;
|
||||||
|
/// <summary>
|
||||||
|
/// 当前是否可以发送数据? 这里可以控制发送次数, 一秒30帧数据左右
|
||||||
|
/// </summary>
|
||||||
|
public static bool CanSent { get { return canSent; } }
|
||||||
|
/// <summary>
|
||||||
|
/// 设置可发送时间 默认30次/秒
|
||||||
|
/// </summary>
|
||||||
|
public float CanSentTime = 1f / 30f;
|
||||||
|
|
||||||
|
private void LateUpdate()
|
||||||
|
{
|
||||||
|
if (Time.time > time)
|
||||||
|
{
|
||||||
|
time = Time.time + CanSentTime;
|
||||||
|
canSent = true;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
canSent = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
|
@ -0,0 +1,50 @@
|
||||||
|
#if UNITY_STANDALONE || UNITY_ANDROID || UNITY_IOS || UNITY_WSA || UNITY_WEBGL
|
||||||
|
using System;
|
||||||
|
|
||||||
|
namespace Net.Component
|
||||||
|
{
|
||||||
|
public enum SerializeAdapterType
|
||||||
|
{
|
||||||
|
Default,//默认序列化, protobuff + json
|
||||||
|
PB_JSON_FAST,//快速序列化 protobuff + json
|
||||||
|
Binary,//快速序列化 需要注册远程类型
|
||||||
|
Binary2,//极速序列化 Binary + Binary2 需要生成序列化类型, 菜单GameDesigner/Netowrk/Fast2BuildTools
|
||||||
|
Binary3//极速序列化 需要生成序列化类型, 菜单GameDesigner/Netowrk/Fast2BuildTools
|
||||||
|
}
|
||||||
|
|
||||||
|
[Obsolete("此组件已弃用, 内部已自动匹配适配器, 无需手动处理")]
|
||||||
|
public class SerializeAdapter : SingleCase<SerializeAdapter>
|
||||||
|
{
|
||||||
|
public SerializeAdapterType type;
|
||||||
|
public bool isEncrypt = false;//数据加密?
|
||||||
|
public int password = 758426581;
|
||||||
|
|
||||||
|
protected override void Awake()
|
||||||
|
{
|
||||||
|
base.Awake();
|
||||||
|
Init();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Init()
|
||||||
|
{
|
||||||
|
var cm = GetComponent<ClientManager>();
|
||||||
|
switch (type) {
|
||||||
|
case SerializeAdapterType.Default:
|
||||||
|
break;
|
||||||
|
case SerializeAdapterType.PB_JSON_FAST:
|
||||||
|
cm.client.AddAdapter(new Adapter.SerializeFastAdapter() { IsEncrypt = isEncrypt, Password = password });
|
||||||
|
break;
|
||||||
|
case SerializeAdapterType.Binary:
|
||||||
|
cm.client.AddAdapter(new Adapter.SerializeAdapter() { IsEncrypt = isEncrypt, Password = password });
|
||||||
|
break;
|
||||||
|
case SerializeAdapterType.Binary2:
|
||||||
|
cm.client.AddAdapter(new Adapter.SerializeAdapter2() { IsEncrypt = isEncrypt, Password = password });
|
||||||
|
break;
|
||||||
|
case SerializeAdapterType.Binary3:
|
||||||
|
cm.client.AddAdapter(new Adapter.SerializeAdapter3() { IsEncrypt = isEncrypt, Password = password });
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
|
@ -0,0 +1,355 @@
|
||||||
|
using System;
|
||||||
|
|
||||||
|
#if UNITY_2020_1_OR_NEWER
|
||||||
|
public static class MathExt
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// 检查算术溢出,如果溢出了,啥都不能做
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="self"></param>
|
||||||
|
/// <param name="value"></param>
|
||||||
|
/// <param name="oper">0:加 1:减 2:乘 3:除 4:取模 5:异或 6:与</param>
|
||||||
|
/// <returns></returns>
|
||||||
|
public static bool Calc(this ref byte self, int value, byte oper)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
self = oper switch
|
||||||
|
{
|
||||||
|
0 => checked((byte)(self + value)),
|
||||||
|
1 => checked((byte)(self - value)),
|
||||||
|
2 => checked((byte)(self * value)),
|
||||||
|
3 => checked((byte)(self / value)),
|
||||||
|
4 => checked((byte)(self % value)),
|
||||||
|
5 => checked((byte)(self ^ value)),
|
||||||
|
6 => checked((byte)(self & value)),
|
||||||
|
_ => throw new Exception("没有这个操作数"),
|
||||||
|
};
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
Net.Event.NDebug.LogError("算术溢出:" + ex);
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 检查算术溢出,如果溢出了,啥都不能做
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="self"></param>
|
||||||
|
/// <param name="value"></param>
|
||||||
|
/// <param name="oper">0:加 1:减 2:乘 3:除 4:取模 5:异或 6:与</param>
|
||||||
|
/// <returns></returns>
|
||||||
|
public static bool Calc(this ref sbyte self, int value, byte oper)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
self = oper switch
|
||||||
|
{
|
||||||
|
0 => checked((sbyte)(self + value)),
|
||||||
|
1 => checked((sbyte)(self - value)),
|
||||||
|
2 => checked((sbyte)(self * value)),
|
||||||
|
3 => checked((sbyte)(self / value)),
|
||||||
|
4 => checked((sbyte)(self % value)),
|
||||||
|
5 => checked((sbyte)(self ^ value)),
|
||||||
|
6 => checked((sbyte)(self & value)),
|
||||||
|
_ => throw new Exception("没有这个操作数"),
|
||||||
|
};
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
Net.Event.NDebug.LogError("算术溢出:" + ex);
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 检查算术溢出,如果溢出了,啥都不能做
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="self"></param>
|
||||||
|
/// <param name="value"></param>
|
||||||
|
/// <param name="oper">0:加 1:减 2:乘 3:除 4:取模 5:异或 6:与</param>
|
||||||
|
/// <returns></returns>
|
||||||
|
public static bool Calc(this ref short self, int value, byte oper)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
self = oper switch
|
||||||
|
{
|
||||||
|
0 => checked((short)(self + value)),
|
||||||
|
1 => checked((short)(self - value)),
|
||||||
|
2 => checked((short)(self * value)),
|
||||||
|
3 => checked((short)(self / value)),
|
||||||
|
4 => checked((short)(self % value)),
|
||||||
|
5 => checked((short)(self ^ value)),
|
||||||
|
6 => checked((short)(self & value)),
|
||||||
|
_ => throw new Exception("没有这个操作数"),
|
||||||
|
};
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
Net.Event.NDebug.LogError("算术溢出:" + ex);
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 检查算术溢出,如果溢出了,啥都不能做
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="self"></param>
|
||||||
|
/// <param name="value"></param>
|
||||||
|
/// <param name="oper">0:加 1:减 2:乘 3:除 4:取模 5:异或 6:与</param>
|
||||||
|
/// <returns></returns>
|
||||||
|
public static bool Calc(this ref ushort self, int value, byte oper)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
self = oper switch
|
||||||
|
{
|
||||||
|
0 => checked((ushort)(self + value)),
|
||||||
|
1 => checked((ushort)(self - value)),
|
||||||
|
2 => checked((ushort)(self * value)),
|
||||||
|
3 => checked((ushort)(self / value)),
|
||||||
|
4 => checked((ushort)(self % value)),
|
||||||
|
5 => checked((ushort)(self ^ value)),
|
||||||
|
6 => checked((ushort)(self & value)),
|
||||||
|
_ => throw new Exception("没有这个操作数"),
|
||||||
|
};
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
Net.Event.NDebug.LogError("算术溢出:" + ex);
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 检查算术溢出,如果溢出了,啥都不能做
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="self"></param>
|
||||||
|
/// <param name="value"></param>
|
||||||
|
/// <param name="oper">0:加 1:减 2:乘 3:除 4:取模 5:异或 6:与</param>
|
||||||
|
/// <returns></returns>
|
||||||
|
public static int CalcRef(this ref int self, int value, byte oper)
|
||||||
|
{
|
||||||
|
return self = Calc(self, value, oper);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 检查算术溢出,如果溢出了,啥都不能做
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="self"></param>
|
||||||
|
/// <param name="value"></param>
|
||||||
|
/// <param name="oper">0:加 1:减 2:乘 3:除 4:取模 5:异或 6:与</param>
|
||||||
|
/// <returns></returns>
|
||||||
|
public static int Calc(this int self, int value, byte oper)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
self = oper switch
|
||||||
|
{
|
||||||
|
0 => checked(self + value),
|
||||||
|
1 => checked(self - value),
|
||||||
|
2 => checked(self * value),
|
||||||
|
3 => checked(self / value),
|
||||||
|
4 => checked(self % value),
|
||||||
|
5 => checked(self ^ value),
|
||||||
|
6 => checked(self & value),
|
||||||
|
_ => throw new Exception("没有这个操作数"),
|
||||||
|
};
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
Net.Event.NDebug.LogError("算术溢出:" + ex);
|
||||||
|
}
|
||||||
|
return self;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 检查算术溢出,如果溢出了,啥都不能做
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="self"></param>
|
||||||
|
/// <param name="value"></param>
|
||||||
|
/// <param name="oper">0:加 1:减 2:乘 3:除 4:取模 5:异或 6:与</param>
|
||||||
|
/// <returns></returns>
|
||||||
|
public static bool Calc(this ref uint self, uint value, byte oper)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
self = oper switch
|
||||||
|
{
|
||||||
|
0 => checked(self + value),
|
||||||
|
1 => checked(self - value),
|
||||||
|
2 => checked(self * value),
|
||||||
|
3 => checked(self / value),
|
||||||
|
4 => checked(self % value),
|
||||||
|
5 => checked(self ^ value),
|
||||||
|
6 => checked(self & value),
|
||||||
|
_ => throw new Exception("没有这个操作数"),
|
||||||
|
};
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
Net.Event.NDebug.LogError("算术溢出:" + ex);
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 检查算术溢出,如果溢出了,啥都不能做
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="self"></param>
|
||||||
|
/// <param name="value"></param>
|
||||||
|
/// <param name="oper">0:加 1:减 2:乘 3:除 4:取模 5:异或 6:与</param>
|
||||||
|
/// <returns></returns>
|
||||||
|
public static bool Calc(this ref float self, float value, byte oper)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
checked
|
||||||
|
{
|
||||||
|
self = oper switch
|
||||||
|
{
|
||||||
|
0 => self + value,
|
||||||
|
1 => self - value,
|
||||||
|
2 => self * value,
|
||||||
|
3 => self / value,
|
||||||
|
4 => self % value,
|
||||||
|
_ => throw new Exception("没有这个操作数"),
|
||||||
|
};
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
Net.Event.NDebug.LogError("算术溢出:" + ex);
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 检查算术溢出,如果溢出了,啥都不能做
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="self"></param>
|
||||||
|
/// <param name="value"></param>
|
||||||
|
/// <param name="oper">0:加 1:减 2:乘 3:除 4:取模 5:异或 6:与</param>
|
||||||
|
/// <returns></returns>
|
||||||
|
public static bool Calc(this ref long self, int value, int oper)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
self = oper switch
|
||||||
|
{
|
||||||
|
0 => checked(self + value),
|
||||||
|
1 => checked(self - value),
|
||||||
|
2 => checked(self * value),
|
||||||
|
3 => checked(self / value),
|
||||||
|
4 => checked(self % value),
|
||||||
|
5 => checked(self ^ value),
|
||||||
|
6 => checked(self & value),
|
||||||
|
_ => throw new Exception("没有这个操作数"),
|
||||||
|
};
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
Net.Event.NDebug.LogError("算术溢出:" + ex);
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 检查算术溢出,如果溢出了,啥都不能做
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="self"></param>
|
||||||
|
/// <param name="value"></param>
|
||||||
|
/// <param name="oper">0:加 1:减 2:乘 3:除 4:取模 5:异或 6:与</param>
|
||||||
|
/// <returns></returns>
|
||||||
|
public static bool Calc(this ref ulong self, ulong value, int oper)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
self = oper switch
|
||||||
|
{
|
||||||
|
0 => checked(self + value),
|
||||||
|
1 => checked(self - value),
|
||||||
|
2 => checked(self * value),
|
||||||
|
3 => checked(self / value),
|
||||||
|
4 => checked(self % value),
|
||||||
|
5 => checked(self ^ value),
|
||||||
|
6 => checked(self & value),
|
||||||
|
_ => throw new Exception("没有这个操作数"),
|
||||||
|
};
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
Net.Event.NDebug.LogError("算术溢出:" + ex);
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 检查算术溢出,如果溢出了,啥都不能做
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="self"></param>
|
||||||
|
/// <param name="value"></param>
|
||||||
|
/// <param name="oper">0:加 1:减 2:乘 3:除 4:取模 5:异或 6:与</param>
|
||||||
|
/// <returns></returns>
|
||||||
|
public static bool Calc(this ref double self, double value, int oper)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
self = oper switch
|
||||||
|
{
|
||||||
|
0 => checked(self + value),
|
||||||
|
1 => checked(self - value),
|
||||||
|
2 => checked(self * value),
|
||||||
|
3 => checked(self / value),
|
||||||
|
4 => checked(self % value),
|
||||||
|
_ => throw new Exception("没有这个操作数"),
|
||||||
|
};
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
Net.Event.NDebug.LogError("算术溢出:" + ex);
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 检查算术溢出,如果溢出了,啥都不能做
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="self"></param>
|
||||||
|
/// <param name="value"></param>
|
||||||
|
/// <param name="oper">0:加 1:减 2:乘 3:除 4:取模 5:异或 6:与</param>
|
||||||
|
/// <returns></returns>
|
||||||
|
public static bool Calc(this ref decimal self, decimal value, int oper)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
self = oper switch
|
||||||
|
{
|
||||||
|
0 => checked(self + value),
|
||||||
|
1 => checked(self - value),
|
||||||
|
2 => checked(self * value),
|
||||||
|
3 => checked(self / value),
|
||||||
|
4 => checked(self % value),
|
||||||
|
_ => throw new Exception("没有这个操作数"),
|
||||||
|
};
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
Net.Event.NDebug.LogError("算术溢出:" + ex);
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
|
@ -0,0 +1,77 @@
|
||||||
|
using System;
|
||||||
|
|
||||||
|
public static class SystemBaseExt
|
||||||
|
{
|
||||||
|
public static string FormatCoin(this int self)
|
||||||
|
{
|
||||||
|
return FormatCoin((long)self);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static string FormatCoin(this long self)
|
||||||
|
{
|
||||||
|
double size = self;
|
||||||
|
string[] units = new string[] { "B", "K", "M", "G", "T", "P" };
|
||||||
|
double mod = 1000;
|
||||||
|
int i = 0;
|
||||||
|
while (size >= mod)
|
||||||
|
{
|
||||||
|
size /= mod;
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
return Math.Round(size, 2) + units[i];
|
||||||
|
}
|
||||||
|
|
||||||
|
public static string FormatRMB(this int self)
|
||||||
|
{
|
||||||
|
return FormatRMB((long)self);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static string FormatRMB(this long self)
|
||||||
|
{
|
||||||
|
double value = self;
|
||||||
|
if (value < 1000d)
|
||||||
|
{
|
||||||
|
return value.ToString("f0");// + "$";
|
||||||
|
}
|
||||||
|
if (value < 10000d)
|
||||||
|
{
|
||||||
|
value /= 1000d;
|
||||||
|
var str = value.ToString("0.##");
|
||||||
|
return str + "千";
|
||||||
|
}
|
||||||
|
|
||||||
|
if (value < 100000000d)//1w-1e显示为0.n万
|
||||||
|
{
|
||||||
|
value /= 10000d;
|
||||||
|
var str = value.ToString("0.##");
|
||||||
|
return str + "万";
|
||||||
|
}
|
||||||
|
|
||||||
|
if (value < 1000000000000d)//1e-1m显示为0.n亿
|
||||||
|
{
|
||||||
|
value /= 100000000d;
|
||||||
|
var str = value.ToString("0.##");
|
||||||
|
return str + "亿";
|
||||||
|
}
|
||||||
|
|
||||||
|
if (value < 10000000000000000d)//1m-1g显示为0.n兆
|
||||||
|
{
|
||||||
|
value /= 1000000000000d;
|
||||||
|
var str = value.ToString("0.##");
|
||||||
|
return str + "兆";
|
||||||
|
}
|
||||||
|
|
||||||
|
if (value < 100000000000000000000d)//1g-1t显示为0.n京
|
||||||
|
{
|
||||||
|
value /= 10000000000000000d;
|
||||||
|
var str = value.ToString("0.##");
|
||||||
|
return str + "京";
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
value /= 100000000000000000000d;
|
||||||
|
var str = value.ToString("0.##");
|
||||||
|
return str + "稊";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,17 @@
|
||||||
|
using System.Collections;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using Net.Client;
|
||||||
|
using Net.Component;
|
||||||
|
using UnityEngine;
|
||||||
|
|
||||||
|
namespace BITKit
|
||||||
|
{
|
||||||
|
[System.Serializable]
|
||||||
|
public class GDNetClientProvider:IGDNetClientProvider
|
||||||
|
|
||||||
|
{
|
||||||
|
[SerializeField] private ClientManager clientManager;
|
||||||
|
public ClientBase GetClient() => clientManager.client;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -0,0 +1,457 @@
|
||||||
|
namespace Net.Client
|
||||||
|
{
|
||||||
|
using global::System;
|
||||||
|
using global::System.Collections.Generic;
|
||||||
|
using global::System.IO;
|
||||||
|
using global::System.Net;
|
||||||
|
using global::System.Net.Sockets;
|
||||||
|
using global::System.Threading;
|
||||||
|
using global::System.Threading.Tasks;
|
||||||
|
using global::System.Security.Cryptography;
|
||||||
|
using Net.Share;
|
||||||
|
using Net.System;
|
||||||
|
using Net.Event;
|
||||||
|
using Net.Helper;
|
||||||
|
using Cysharp.Threading.Tasks;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// TCP客户端类型
|
||||||
|
/// 第三版本 2020.9.14
|
||||||
|
/// </summary>
|
||||||
|
[Serializable]
|
||||||
|
public class TcpClient : ClientBase
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// tcp数据长度(4) + 1CRC协议 = 5
|
||||||
|
/// </summary>
|
||||||
|
protected override int frame { get; set; } = 5;
|
||||||
|
public override bool MD5CRC
|
||||||
|
{
|
||||||
|
get => md5crc;
|
||||||
|
set
|
||||||
|
{
|
||||||
|
md5crc = value;
|
||||||
|
frame = value ? 5 + 16 : 5;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
public override int HeartInterval { get; set; } = 1000 * 60 * 10;//10分钟跳一次
|
||||||
|
public override byte HeartLimit { get; set; } = 2;//确认两次
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 构造可靠传输客户端
|
||||||
|
/// </summary>
|
||||||
|
public TcpClient()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 构造不可靠传输客户端
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="useUnityThread">使用unity多线程?</param>
|
||||||
|
public TcpClient(bool useUnityThread) : this()
|
||||||
|
{
|
||||||
|
UseUnityThread = useUnityThread;
|
||||||
|
}
|
||||||
|
|
||||||
|
~TcpClient()
|
||||||
|
{
|
||||||
|
#if !UNITY_EDITOR
|
||||||
|
Close();
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override UniTask<bool> ConnectResult(string host, int port, int localPort, Action<bool> result)
|
||||||
|
{
|
||||||
|
#if SERVICE
|
||||||
|
return UniTask.Run(() =>
|
||||||
|
#else
|
||||||
|
return UniTask.RunOnThreadPool(() =>
|
||||||
|
#endif
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
Client = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
|
||||||
|
this.localPort = localPort;
|
||||||
|
Client.NoDelay = true;
|
||||||
|
if (localPort != -1)
|
||||||
|
Client.Bind(new IPEndPoint(IPAddress.Any, localPort));
|
||||||
|
Client.Connect(host, port);
|
||||||
|
var segment = BufferPool.Take();
|
||||||
|
segment.Write(PreUserId);
|
||||||
|
Client.Send(segment.ToArray(true));
|
||||||
|
var tick = Environment.TickCount + 8000;
|
||||||
|
while (UID == 0)
|
||||||
|
{
|
||||||
|
Receive(true);
|
||||||
|
if (Environment.TickCount >= tick)
|
||||||
|
throw new Exception("uid赋值失败!连接超时处理");
|
||||||
|
if (!openClient)
|
||||||
|
throw new Exception("客户端调用Close!");
|
||||||
|
}
|
||||||
|
StackStream = new MemoryStream(Config.Config.BaseCapacity);
|
||||||
|
StartupThread();
|
||||||
|
result(true);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
catch(Exception ex)
|
||||||
|
{
|
||||||
|
NDebug.LogError("连接错误:" + ex);
|
||||||
|
Connected = false;
|
||||||
|
Client?.Close();
|
||||||
|
Client = null;
|
||||||
|
result(false);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override bool HeartHandler()
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
if (++heart <= HeartLimit)
|
||||||
|
return true;
|
||||||
|
if (!Connected)
|
||||||
|
Reconnection();
|
||||||
|
else
|
||||||
|
Send(NetCmd.SendHeartbeat, new byte[0]);
|
||||||
|
}
|
||||||
|
catch
|
||||||
|
{
|
||||||
|
}
|
||||||
|
return openClient & CurrReconnect < ReconnectCount;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override void SendRTDataHandle()
|
||||||
|
{
|
||||||
|
SendDataHandle(rtRPCModels, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override byte[] PackData(Segment stream)
|
||||||
|
{
|
||||||
|
stream.Flush();
|
||||||
|
if (MD5CRC)
|
||||||
|
{
|
||||||
|
MD5 md5 = new MD5CryptoServiceProvider();
|
||||||
|
var head = frame;
|
||||||
|
byte[] retVal = md5.ComputeHash(stream, head, stream.Count - head);
|
||||||
|
EncryptHelper.ToEncrypt(Password, retVal);
|
||||||
|
int len = stream.Count - head;
|
||||||
|
var lenBytes = BitConverter.GetBytes(len);
|
||||||
|
byte crc = CRCHelper.CRC8(lenBytes, 0, lenBytes.Length);
|
||||||
|
stream.Position = 0;
|
||||||
|
stream.Write(lenBytes, 0, 4);
|
||||||
|
stream.WriteByte(crc);
|
||||||
|
stream.Write(retVal, 0, retVal.Length);
|
||||||
|
stream.Position = len + head;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
int len = stream.Count - frame;
|
||||||
|
var lenBytes = BitConverter.GetBytes(len);
|
||||||
|
byte retVal = CRCHelper.CRC8(lenBytes, 0, lenBytes.Length);
|
||||||
|
stream.Position = 0;
|
||||||
|
stream.Write(lenBytes, 0, 4);
|
||||||
|
stream.WriteByte(retVal);
|
||||||
|
stream.Position = len + frame;
|
||||||
|
}
|
||||||
|
return stream.ToArray();
|
||||||
|
}
|
||||||
|
#if TEST1
|
||||||
|
ListSafe<byte> list = new ListSafe<byte>();
|
||||||
|
#endif
|
||||||
|
protected override void SendByteData(byte[] buffer, bool reliable)
|
||||||
|
{
|
||||||
|
sendCount += buffer.Length;
|
||||||
|
sendAmount++;
|
||||||
|
if (Client.Poll(1, SelectMode.SelectWrite))
|
||||||
|
{
|
||||||
|
#if TEST1
|
||||||
|
list.AddRange(buffer);
|
||||||
|
do
|
||||||
|
{
|
||||||
|
var buffer1 = list.GetRemoveRange(0, RandomHelper.Range(0, buffer.Length));
|
||||||
|
Net.Server.TcpServer.Instance.ReceiveTest(buffer1);
|
||||||
|
}
|
||||||
|
while (rtRPCModels.Count == 0 & list.Count > 0);
|
||||||
|
#else
|
||||||
|
int count = Client.Send(buffer, 0, buffer.Length, SocketFlags.None);
|
||||||
|
if (count <= 0)
|
||||||
|
OnSendErrorHandle?.Invoke(buffer, reliable);
|
||||||
|
else if (count != buffer.Length)
|
||||||
|
NDebug.Log($"发送了{buffer.Length - count}个字节失败!");
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
NDebug.Log("缓冲区已满,等待接收中!");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override void ResolveBuffer(ref Segment buffer, bool isTcp)
|
||||||
|
{
|
||||||
|
#if TEST1
|
||||||
|
if (StackStream == null)
|
||||||
|
StackStream = BufferStreamShare.Take();
|
||||||
|
#endif
|
||||||
|
heart = 0;
|
||||||
|
if (stack > 0)
|
||||||
|
{
|
||||||
|
stack++;
|
||||||
|
StackStream.Seek(stackIndex, SeekOrigin.Begin);
|
||||||
|
int size = buffer.Count - buffer.Position;
|
||||||
|
stackIndex += size;
|
||||||
|
StackStream.Write(buffer, buffer.Position, size);
|
||||||
|
if (stackIndex < stackCount)
|
||||||
|
{
|
||||||
|
InvokeRevdRTProgress(stackIndex, stackCount);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
var count = (int)StackStream.Position;//.Length; //错误问题,不能用length, 这是文件总长度, 之前可能已经有很大一波数据
|
||||||
|
BufferPool.Push(buffer);//要回收掉, 否则会提示内存泄露
|
||||||
|
buffer = BufferPool.Take(count);//ref 才不会导致提示内存泄露
|
||||||
|
StackStream.Seek(0, SeekOrigin.Begin);
|
||||||
|
StackStream.Read(buffer, 0, count);
|
||||||
|
buffer.Count = count;
|
||||||
|
}
|
||||||
|
while (buffer.Position < buffer.Count)
|
||||||
|
{
|
||||||
|
if (buffer.Position + 5 > buffer.Count)//流数据偶尔小于frame头部字节
|
||||||
|
{
|
||||||
|
var position = buffer.Position;
|
||||||
|
var count = buffer.Count - position;
|
||||||
|
stackIndex = count;
|
||||||
|
stackCount = 0;
|
||||||
|
StackStream.Seek(0, SeekOrigin.Begin);
|
||||||
|
StackStream.Write(buffer, position, count);
|
||||||
|
stack++;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
var lenBytes = buffer.Read(4);
|
||||||
|
byte crcCode = buffer.ReadByte();//CRC检验索引
|
||||||
|
byte retVal = CRCHelper.CRC8(lenBytes, 0, 4);
|
||||||
|
if (crcCode != retVal)
|
||||||
|
{
|
||||||
|
stack = 0;
|
||||||
|
NDebug.LogError($"[{UID}]CRC校验失败!");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
int size = BitConverter.ToInt32(lenBytes, 0);
|
||||||
|
if (size < 0 | size > PackageSize)//如果出现解析的数据包大小有问题,则不处理
|
||||||
|
{
|
||||||
|
stack = 0;
|
||||||
|
NDebug.LogError($"[{UID}]数据被拦截修改或数据量太大: size:{size},如果想传输大数据,请设置PackageSize属性");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
int value = MD5CRC ? 16 : 0;
|
||||||
|
if (buffer.Position + size + value <= buffer.Count)
|
||||||
|
{
|
||||||
|
stack = 0;
|
||||||
|
var count = buffer.Count;//此长度可能会有连续的数据(粘包)
|
||||||
|
buffer.Count = buffer.Position + value + size;//需要指定一个完整的数据长度给内部解析
|
||||||
|
base.ResolveBuffer(ref buffer, true);
|
||||||
|
buffer.Count = count;//解析完成后再赋值原来的总长
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
var position = buffer.Position - 5;
|
||||||
|
var count = buffer.Count - position;
|
||||||
|
stackIndex = count;
|
||||||
|
stackCount = size;
|
||||||
|
StackStream.Seek(0, SeekOrigin.Begin);
|
||||||
|
StackStream.Write(buffer, position, count);
|
||||||
|
stack++;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void Close(bool await = true, int millisecondsTimeout = 1000)
|
||||||
|
{
|
||||||
|
SendRT(NetCmd.Disconnect, new byte[0]);
|
||||||
|
SendDirect();
|
||||||
|
Connected = false;
|
||||||
|
openClient = false;
|
||||||
|
NetworkState = NetworkState.ConnectClosed;
|
||||||
|
InvokeInMainThread(OnCloseConnectHandle);
|
||||||
|
if (await) Thread.Sleep(millisecondsTimeout);//给update线程一秒的时间处理关闭事件
|
||||||
|
AbortedThread();
|
||||||
|
Client?.Close();
|
||||||
|
Client = null;
|
||||||
|
StackStream?.Close();
|
||||||
|
StackStream = null;
|
||||||
|
stack = 0;
|
||||||
|
stackIndex = 0;
|
||||||
|
stackCount = 0;
|
||||||
|
UID = 0;
|
||||||
|
CurrReconnect = 0;
|
||||||
|
if (Instance == this) Instance = null;
|
||||||
|
if (Gcp != null) Gcp.Dispose();
|
||||||
|
NDebug.Log("客户端已关闭!");
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// tcp压力测试
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="ip">服务器ip</param>
|
||||||
|
/// <param name="port">服务器端口</param>
|
||||||
|
/// <param name="clientLen">测试客户端数量</param>
|
||||||
|
/// <param name="dataLen">每个客户端数据大小</param>
|
||||||
|
public static CancellationTokenSource Testing(string ip, int port, int clientLen, int dataLen, int millisecondsTimeout, Action<TcpClientTest> onInit = null, Action<List<TcpClientTest>> fpsAct = null, IAdapter adapter = null)
|
||||||
|
{
|
||||||
|
var cts = new CancellationTokenSource();
|
||||||
|
Task.Run(() =>
|
||||||
|
{
|
||||||
|
var clients = new List<TcpClientTest>();
|
||||||
|
for (int i = 0; i < clientLen; i++)
|
||||||
|
{
|
||||||
|
var client = new TcpClientTest();
|
||||||
|
onInit?.Invoke(client);
|
||||||
|
if(adapter != null)
|
||||||
|
client.AddAdapter(adapter);
|
||||||
|
try {
|
||||||
|
client.Connect(ip, port);
|
||||||
|
} catch (Exception ex) {
|
||||||
|
NDebug.LogError(ex);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
clients.Add(client);
|
||||||
|
}
|
||||||
|
var buffer = new byte[dataLen];
|
||||||
|
Task.Run(() =>
|
||||||
|
{
|
||||||
|
while (!cts.IsCancellationRequested)
|
||||||
|
{
|
||||||
|
Thread.Sleep(1000);
|
||||||
|
fpsAct?.Invoke(clients);
|
||||||
|
for (int i = 0; i < clients.Count; i++)
|
||||||
|
{
|
||||||
|
clients[i].NetworkFlowHandler();
|
||||||
|
clients[i].fps = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
int threadNum = (clientLen / 1000) + 1;
|
||||||
|
for (int i = 0; i < threadNum; i++)
|
||||||
|
{
|
||||||
|
int index = i * 1000;
|
||||||
|
int end = index + 1000;
|
||||||
|
if (index >= clientLen)
|
||||||
|
break;
|
||||||
|
Task.Run(() =>
|
||||||
|
{
|
||||||
|
if (end > clientLen)
|
||||||
|
end = clientLen;
|
||||||
|
var timer = new TimerTick();
|
||||||
|
while (!cts.IsCancellationRequested)
|
||||||
|
{
|
||||||
|
bool canSend = false;
|
||||||
|
var tick = (uint)Environment.TickCount;
|
||||||
|
if (timer.CheckTimeout(tick, (uint)millisecondsTimeout, true))
|
||||||
|
{
|
||||||
|
canSend = true;
|
||||||
|
}
|
||||||
|
for (int ii = index; ii < end; ii++)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
var client = clients[ii];
|
||||||
|
if (client.Client == null)
|
||||||
|
continue;
|
||||||
|
if (!client.Client.Connected)
|
||||||
|
continue;
|
||||||
|
if (client.Client.Poll(0, SelectMode.SelectRead))
|
||||||
|
{
|
||||||
|
var buffer1 = BufferPool.Take(65535);
|
||||||
|
buffer1.Count = client.Client.Receive(buffer1, 0, ushort.MaxValue, SocketFlags.None, out var errorCode);
|
||||||
|
if(errorCode == SocketError.Success)
|
||||||
|
client.ResolveBuffer(ref buffer1, false);
|
||||||
|
BufferPool.Push(buffer1);
|
||||||
|
}
|
||||||
|
if (canSend)
|
||||||
|
{
|
||||||
|
client.SendRT(NetCmd.Local, buffer);
|
||||||
|
//client.AddOperation(new Operation(66, buffer));
|
||||||
|
client.SendDirect();
|
||||||
|
}
|
||||||
|
client.NetworkTick();
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
NDebug.LogError(ex);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
while (!cts.IsCancellationRequested)
|
||||||
|
Thread.Sleep(30);
|
||||||
|
Thread.Sleep(100);
|
||||||
|
for (int i = 0; i < clients.Count; i++)
|
||||||
|
clients[i].Close(false);
|
||||||
|
}, cts.Token);
|
||||||
|
return cts;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public class TcpClientTest : TcpClient
|
||||||
|
{
|
||||||
|
public int fps;
|
||||||
|
public int revdSize { get { return receiveCount; } }
|
||||||
|
public int sendSize { get { return sendCount; } }
|
||||||
|
public int sendNum { get { return sendAmount; } }
|
||||||
|
public int revdNum { get { return receiveAmount; } }
|
||||||
|
public int resolveNum { get { return receiveAmount; } }
|
||||||
|
|
||||||
|
public TcpClientTest()
|
||||||
|
{
|
||||||
|
OnReceiveDataHandle += (model) => { fps++; };
|
||||||
|
OnOperationSync += (list) => { fps++; };
|
||||||
|
}
|
||||||
|
protected override UniTask<bool> ConnectResult(string host, int port, int localPort, Action<bool> result)
|
||||||
|
{
|
||||||
|
Client = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
|
||||||
|
this.localPort = localPort;
|
||||||
|
Client.Connect(host, port);
|
||||||
|
Client.Blocking = false;
|
||||||
|
Client.NoDelay = true;
|
||||||
|
var segment = BufferPool.Take();
|
||||||
|
segment.Write(PreUserId);
|
||||||
|
Client.Send(segment.ToArray(true));
|
||||||
|
Connected = true;
|
||||||
|
StackStream = new MemoryStream(Config.Config.BaseCapacity);
|
||||||
|
return UniTask.FromResult(Connected);
|
||||||
|
}
|
||||||
|
protected override void StartupThread() { }
|
||||||
|
|
||||||
|
//protected override void OnConnected(bool result) { }
|
||||||
|
|
||||||
|
//protected override void ResolveBuffer(ref Segment buffer, bool isTcp)
|
||||||
|
//{
|
||||||
|
// base.ResolveBuffer(ref buffer, isTcp);
|
||||||
|
//}
|
||||||
|
protected unsafe override void SendByteData(byte[] buffer, bool reliable)
|
||||||
|
{
|
||||||
|
sendCount += buffer.Length;
|
||||||
|
sendAmount++;
|
||||||
|
#if WINDOWS
|
||||||
|
fixed (byte* ptr = buffer)
|
||||||
|
Win32KernelAPI.send(Client.Handle, ptr, buffer.Length, SocketFlags.None);
|
||||||
|
#else
|
||||||
|
Client.Send(buffer, 0, buffer.Length, SocketFlags.None);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
//protected internal override byte[] OnSerializeOptInternal(OperationList list)
|
||||||
|
//{
|
||||||
|
// return new byte[0];
|
||||||
|
//}
|
||||||
|
//protected internal override OperationList OnDeserializeOptInternal(byte[] buffer, int index, int count)
|
||||||
|
//{
|
||||||
|
// return default;
|
||||||
|
//}
|
||||||
|
public override string ToString()
|
||||||
|
{
|
||||||
|
return $"uid:{UID} conv:{Connected}";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,256 @@
|
||||||
|
namespace Net.Client
|
||||||
|
{
|
||||||
|
using global::System;
|
||||||
|
using global::System.Net;
|
||||||
|
using global::System.Collections.Generic;
|
||||||
|
using global::System.IO;
|
||||||
|
using global::System.Net.Sockets;
|
||||||
|
using global::System.Reflection;
|
||||||
|
using global::System.Threading;
|
||||||
|
using global::System.Threading.Tasks;
|
||||||
|
using Net.Share;
|
||||||
|
using Net.System;
|
||||||
|
using Net.Helper;
|
||||||
|
using Net.Plugins;
|
||||||
|
using Net.Event;
|
||||||
|
using Cysharp.Threading.Tasks;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Udp网络客户端
|
||||||
|
/// 在安卓端必须设置可以后台运行, 如果不设置,当你按下home键后,app的所有线程将会被暂停,这会影响网络心跳检测线程,导致网络中断
|
||||||
|
/// 解决方法 : 在android项目AndroidManifest.xml文件中的activity中添加如下内容:
|
||||||
|
/// android:configChanges="fontScale|keyboard|keyboardHidden|locale|mnc|mcc|navigation|orientation|screenLayout|screenSize|smallestScreenSize|uiMode|touchscreen"
|
||||||
|
/// 详情请看此博文:https://www.cnblogs.com/nanwei/p/9125316.html
|
||||||
|
/// 或这个博文: http://www.voidcn.com/article/p-yakpcmce-bpk.html
|
||||||
|
/// </summary>
|
||||||
|
[Serializable]
|
||||||
|
public class UdpClient : ClientBase
|
||||||
|
{
|
||||||
|
public override int MTU { get => Gcp.MTU; set => Gcp.MTU = (ushort)value; }
|
||||||
|
public override int RTO { get => Gcp.RTO; set => Gcp.RTO = value; }
|
||||||
|
public override int MTPS { get => Gcp.MTPS; set => Gcp.MTPS = value; }
|
||||||
|
public override FlowControlMode FlowControl { get => Gcp.FlowControl; set => Gcp.FlowControl = value; }
|
||||||
|
public override Action<RTProgress> OnRevdRTProgress { get => Gcp.OnRevdProgress; set => Gcp.OnRevdProgress = value; }
|
||||||
|
public override Action<RTProgress> OnSendRTProgress { get => Gcp.OnSendProgress; set => Gcp.OnSendProgress = value; }
|
||||||
|
/// <summary>
|
||||||
|
/// 构造udp可靠客户端
|
||||||
|
/// </summary>
|
||||||
|
public UdpClient()
|
||||||
|
{
|
||||||
|
Gcp = new GcpKernel();
|
||||||
|
Gcp.OnSender += (bytes) => {
|
||||||
|
Send(NetCmd.ReliableTransport, bytes);
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 构造udp可靠客户端
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="useUnityThread">使用unity多线程?</param>
|
||||||
|
public UdpClient(bool useUnityThread) : this()
|
||||||
|
{
|
||||||
|
UseUnityThread = useUnityThread;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 获取p2p IP和端口, 通过client.OnP2PCallback事件回调
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="uid"></param>
|
||||||
|
public void GetP2P(int uid)
|
||||||
|
{
|
||||||
|
SendRT(NetCmd.P2P, BitConverter.GetBytes(uid));
|
||||||
|
}
|
||||||
|
|
||||||
|
#if UDPTEST
|
||||||
|
protected override void StartupThread()
|
||||||
|
{
|
||||||
|
base.StartupThread();
|
||||||
|
Gcp.RemotePoint = Client.LocalEndPoint;
|
||||||
|
}
|
||||||
|
protected override void ReceiveHandle()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
internal void ReceiveTest(byte[] buffer)//本机测试
|
||||||
|
{
|
||||||
|
var segment = new Segment(buffer, false);
|
||||||
|
receiveCount += segment.Count;
|
||||||
|
receiveAmount++;
|
||||||
|
heart = 0;
|
||||||
|
ResolveBuffer(ref segment, false);
|
||||||
|
revdLoopNum++;
|
||||||
|
}
|
||||||
|
internal void DataHandleTest(byte[] buffer)//本机测试
|
||||||
|
{
|
||||||
|
DataHandle(buffer);
|
||||||
|
}
|
||||||
|
protected override void SendByteData(byte[] buffer, bool reliable)
|
||||||
|
{
|
||||||
|
sendCount += buffer.Length;
|
||||||
|
sendAmount++;
|
||||||
|
if (buffer.Length <= 65507)
|
||||||
|
(Net.Server.UdpServer.Instance as Net.Server.UdpServer).ReceiveTest(buffer, Client.LocalEndPoint); //Client.Send(buffer, 0, buffer.Length, SocketFlags.None);
|
||||||
|
else
|
||||||
|
NDebug.LogError("数据过大, 请使用SendRT发送...");
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// udp压力测试
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="ip">服务器ip</param>
|
||||||
|
/// <param name="port">服务器端口</param>
|
||||||
|
/// <param name="clientLen">测试客户端数量</param>
|
||||||
|
/// <param name="dataLen">每个客户端数据大小</param>
|
||||||
|
public unsafe static CancellationTokenSource Testing(string ip, int port, int clientLen, int dataLen, int millisecondsTimeout, Action<UdpClientTest> onInit = null, Action<List<UdpClientTest>> fpsAct = null, IAdapter adapter = null)
|
||||||
|
{
|
||||||
|
var cts = new CancellationTokenSource();
|
||||||
|
Task.Run(() =>
|
||||||
|
{
|
||||||
|
var clients = new List<UdpClientTest>();
|
||||||
|
for (int i = 0; i < clientLen; i++)
|
||||||
|
{
|
||||||
|
var client = new UdpClientTest();
|
||||||
|
onInit?.Invoke(client);
|
||||||
|
if(adapter!=null)
|
||||||
|
client.AddAdapter(adapter);
|
||||||
|
client.Connect(ip,port);
|
||||||
|
clients.Add(client);
|
||||||
|
}
|
||||||
|
var buffer = new byte[dataLen];
|
||||||
|
Task.Run(()=>
|
||||||
|
{
|
||||||
|
while (!cts.IsCancellationRequested)
|
||||||
|
{
|
||||||
|
Thread.Sleep(1000);
|
||||||
|
fpsAct?.Invoke(clients);
|
||||||
|
for (int i = 0; i < clients.Count; i++)
|
||||||
|
{
|
||||||
|
clients[i].NetworkFlowHandler();
|
||||||
|
clients[i].fps = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
int threadNum = (clientLen / 1000) + 1;
|
||||||
|
for (int i = 0; i < threadNum; i++)
|
||||||
|
{
|
||||||
|
int index = i * 1000;
|
||||||
|
int end = index + 1000;
|
||||||
|
if (index >= clientLen)
|
||||||
|
break;
|
||||||
|
Task.Run(()=>
|
||||||
|
{
|
||||||
|
if (end > clientLen)
|
||||||
|
end = clientLen;
|
||||||
|
var tick = Environment.TickCount + millisecondsTimeout;
|
||||||
|
while (!cts.IsCancellationRequested)
|
||||||
|
{
|
||||||
|
bool canSend = false;
|
||||||
|
if (Environment.TickCount >= tick)
|
||||||
|
{
|
||||||
|
tick = Environment.TickCount + millisecondsTimeout;
|
||||||
|
canSend = true;
|
||||||
|
}
|
||||||
|
for (int ii = index; ii < end; ii++)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
var client = clients[ii];
|
||||||
|
if (canSend)
|
||||||
|
{
|
||||||
|
//client.SendRT(NetCmd.Local, buffer);
|
||||||
|
client.AddOperation(new Operation(NetCmd.Local, buffer));
|
||||||
|
}
|
||||||
|
client.Update();
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
Event.NDebug.LogError(ex);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
while (!cts.IsCancellationRequested)
|
||||||
|
Thread.Sleep(30);
|
||||||
|
Thread.Sleep(100);
|
||||||
|
for (int i = 0; i < clients.Count; i++)
|
||||||
|
clients[i].Close(false);
|
||||||
|
}, cts.Token);
|
||||||
|
return cts;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public class UdpClientTest : UdpClient
|
||||||
|
{
|
||||||
|
public int fps;
|
||||||
|
public int revdSize { get { return receiveCount; } }
|
||||||
|
public int sendSize { get { return sendCount; } }
|
||||||
|
public int sendNum { get { return sendAmount; } }
|
||||||
|
public int revdNum { get { return receiveAmount; } }
|
||||||
|
public int resolveNum { get { return receiveAmount; } }
|
||||||
|
private byte[] addressBuffer;
|
||||||
|
public UdpClientTest()
|
||||||
|
{
|
||||||
|
OnReceiveDataHandle += (model) => { fps++; };
|
||||||
|
OnOperationSync += (list) => { fps++; };
|
||||||
|
}
|
||||||
|
protected override UniTask<bool> ConnectResult(string host, int port, int localPort, Action<bool> result)
|
||||||
|
{
|
||||||
|
Client = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp);
|
||||||
|
this.localPort = localPort;
|
||||||
|
Client.Connect(host, port);
|
||||||
|
Client.Blocking = false;
|
||||||
|
#if WINDOWS
|
||||||
|
var socketAddress = Client.RemoteEndPoint.Serialize();
|
||||||
|
addressBuffer = (byte[])socketAddress.GetType().GetField("m_Buffer", BindingFlags.NonPublic | BindingFlags.Instance).GetValue(socketAddress);
|
||||||
|
#endif
|
||||||
|
rPCModels.Enqueue(new RPCModel(NetCmd.Connect, new byte[0]));
|
||||||
|
SendDirect();
|
||||||
|
Connected = true;
|
||||||
|
result(true);
|
||||||
|
return UniTask.FromResult(Connected);
|
||||||
|
}
|
||||||
|
protected override void StartupThread() { }
|
||||||
|
|
||||||
|
//protected override void OnConnected(bool result) { NetworkState = NetworkState.Connected; }
|
||||||
|
|
||||||
|
//protected override void ResolveBuffer(ref Segment buffer, bool isTcp)
|
||||||
|
//{
|
||||||
|
// base.ResolveBuffer(ref buffer, isTcp);
|
||||||
|
//}
|
||||||
|
protected unsafe override void SendByteData(byte[] buffer, bool reliable)
|
||||||
|
{
|
||||||
|
sendCount += buffer.Length;
|
||||||
|
sendAmount++;
|
||||||
|
#if WINDOWS
|
||||||
|
fixed (byte* ptr = buffer)
|
||||||
|
Win32KernelAPI.sendto(Client.Handle, ptr, buffer.Length, SocketFlags.None, addressBuffer, 16);
|
||||||
|
#else
|
||||||
|
Client.Send(buffer, 0, buffer.Length, SocketFlags.None);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
//protected internal override byte[] OnSerializeOptInternal(OperationList list)
|
||||||
|
//{
|
||||||
|
// return new byte[0];
|
||||||
|
//}
|
||||||
|
//protected internal override OperationList OnDeserializeOptInternal(byte[] buffer, int index, int count)
|
||||||
|
//{
|
||||||
|
// return default;
|
||||||
|
//}
|
||||||
|
/// <summary>
|
||||||
|
/// 单线程更新,需要开发者自动调用更新
|
||||||
|
/// </summary>
|
||||||
|
public void Update()
|
||||||
|
{
|
||||||
|
if (!Connected)
|
||||||
|
return;
|
||||||
|
Receive(false);
|
||||||
|
SendDirect();
|
||||||
|
NetworkTick();
|
||||||
|
}
|
||||||
|
public override string ToString()
|
||||||
|
{
|
||||||
|
return $"uid:{UID} conv:{Connected}";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,290 @@
|
||||||
|
using Net.Share;
|
||||||
|
using Net.System;
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.IO;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Net;
|
||||||
|
using System.Net.Sockets;
|
||||||
|
using System.Text;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
|
namespace Net.Plugins
|
||||||
|
{
|
||||||
|
class Cmd
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// 网络帧
|
||||||
|
/// </summary>
|
||||||
|
internal const byte Frame = 2;
|
||||||
|
/// <summary>
|
||||||
|
/// 网络帧确认
|
||||||
|
/// </summary>
|
||||||
|
internal const byte Ack = 4;
|
||||||
|
/// <summary>
|
||||||
|
/// 冗余帧
|
||||||
|
/// </summary>
|
||||||
|
internal const byte DAck = 6;
|
||||||
|
}
|
||||||
|
|
||||||
|
class DataFrame
|
||||||
|
{
|
||||||
|
private int hashCode;
|
||||||
|
internal byte[] buffer;
|
||||||
|
internal int tick;
|
||||||
|
public DataFrame()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
public DataFrame(int hashCode, byte[] buffer)
|
||||||
|
{
|
||||||
|
this.hashCode = hashCode;
|
||||||
|
this.buffer = buffer;
|
||||||
|
}
|
||||||
|
public override int GetHashCode()
|
||||||
|
{
|
||||||
|
return hashCode;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class DataPackage
|
||||||
|
{
|
||||||
|
internal Segment revderBuffer;
|
||||||
|
internal int revderFrameEnd;
|
||||||
|
internal byte[] revderHash;
|
||||||
|
internal int revderHashCount;
|
||||||
|
internal bool finish;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gcp可靠协议核心类
|
||||||
|
/// </summary>
|
||||||
|
public class GcpKernel : IGcp, IDisposable
|
||||||
|
{
|
||||||
|
private uint pushPackage;
|
||||||
|
private uint senderPackage;
|
||||||
|
private uint revderPackage;
|
||||||
|
private readonly Queue<byte[]> senderQueue = new Queue<byte[]>();
|
||||||
|
private readonly Queue<Segment> revderQueue = new Queue<Segment>();
|
||||||
|
public Action<byte[]> OnSender { get; set; }
|
||||||
|
public Action<RTProgress> OnSendProgress { get; set; }
|
||||||
|
public Action<RTProgress> OnRevdProgress { get; set; }
|
||||||
|
private readonly MyDictionary<uint, MyDictionary<int, DataFrame>> senderDict = new MyDictionary<uint, MyDictionary<int, DataFrame>>();
|
||||||
|
private readonly MyDictionary<uint, DataPackage> revderDict = new MyDictionary<uint, DataPackage>();
|
||||||
|
public EndPoint RemotePoint { get; set; }
|
||||||
|
private readonly object SyncRoot = new object();
|
||||||
|
private int tick;
|
||||||
|
private int flowTick;
|
||||||
|
private int currFlow;
|
||||||
|
private int progressTick;
|
||||||
|
public ushort MTU { get; set; } = 1300;
|
||||||
|
public int RTO { get; set; } = 1000;
|
||||||
|
private int ackNumber = 1;
|
||||||
|
private int currAck;
|
||||||
|
public int MTPS { get; set; } = 1024 * 1024;
|
||||||
|
public int ProgressDataLen { get; set; } = ushort.MaxValue;//要求数据大于多少才会调用发送,接收进度值
|
||||||
|
public FlowControlMode FlowControl { get; set; } = FlowControlMode.Normal;
|
||||||
|
|
||||||
|
public void Update()
|
||||||
|
{
|
||||||
|
lock (SyncRoot)
|
||||||
|
{
|
||||||
|
CheckNextSend();
|
||||||
|
tick = Environment.TickCount;
|
||||||
|
if (tick >= flowTick)
|
||||||
|
{
|
||||||
|
flowTick = tick + 1000;
|
||||||
|
currFlow = 0;
|
||||||
|
currAck = 0;
|
||||||
|
ackNumber = FlowControl == FlowControlMode.Normal ? 1 : 100;
|
||||||
|
}
|
||||||
|
if (senderDict.Count <= 0)
|
||||||
|
return;
|
||||||
|
var length = senderPackage + senderDict.Count;
|
||||||
|
for (uint i = senderPackage; i < length; i++)
|
||||||
|
{
|
||||||
|
if (!FastRetransmit(i))
|
||||||
|
if(i == senderPackage)
|
||||||
|
senderPackage++;
|
||||||
|
if (currFlow >= MTPS | currAck >= ackNumber)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
public int Receive(out Segment segment)
|
||||||
|
{
|
||||||
|
lock (SyncRoot)
|
||||||
|
{
|
||||||
|
if (revderQueue.Count <= 0)
|
||||||
|
{
|
||||||
|
segment = null;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
segment = revderQueue.Dequeue();
|
||||||
|
return segment.Count;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
public void Send(byte[] buffer)
|
||||||
|
{
|
||||||
|
lock (SyncRoot)
|
||||||
|
{
|
||||||
|
senderQueue.Enqueue(buffer);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
private void CheckNextSend()
|
||||||
|
{
|
||||||
|
if (senderQueue.Count > 0)
|
||||||
|
{
|
||||||
|
var current = senderQueue.Dequeue();
|
||||||
|
var count = current.Length;
|
||||||
|
var frameEnd = (int)Math.Ceiling(count / (float)MTU);
|
||||||
|
using (var segment = BufferPool.Take())
|
||||||
|
{
|
||||||
|
var dic = new MyDictionary<int, DataFrame>(frameEnd);
|
||||||
|
senderDict.Add(pushPackage, dic);
|
||||||
|
for (int serialNo = 0; serialNo < frameEnd; serialNo++)
|
||||||
|
{
|
||||||
|
segment.SetPositionLength(0);
|
||||||
|
segment.WriteByte(Cmd.Frame);
|
||||||
|
segment.Write(pushPackage);
|
||||||
|
segment.Write(serialNo);
|
||||||
|
segment.Write(count);
|
||||||
|
var offset = serialNo * MTU;
|
||||||
|
segment.Write(current, offset, offset + MTU >= count ? count - offset : MTU);
|
||||||
|
var dataFrame = new DataFrame(serialNo, segment.ToArray());
|
||||||
|
dic.Add(serialNo, dataFrame);
|
||||||
|
}
|
||||||
|
pushPackage++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
public void Input(byte[] buffer)
|
||||||
|
{
|
||||||
|
lock (SyncRoot)
|
||||||
|
{
|
||||||
|
var segment = new Segment(buffer, false);
|
||||||
|
var flags = segment.ReadByte();
|
||||||
|
if (flags == Cmd.Frame)
|
||||||
|
{
|
||||||
|
var package = segment.ReadUInt32();
|
||||||
|
var serialNo = segment.ReadInt32();
|
||||||
|
var dataLen = segment.ReadInt32();
|
||||||
|
if (package < revderPackage)
|
||||||
|
goto J;
|
||||||
|
if (!revderDict.TryGetValue(package, out var dp))
|
||||||
|
revderDict.Add(package, dp = new DataPackage());
|
||||||
|
if (dp.revderBuffer == null)
|
||||||
|
{
|
||||||
|
dp.revderBuffer = BufferPool.Take(dataLen);
|
||||||
|
dp.revderBuffer.Count = dataLen;
|
||||||
|
dp.revderFrameEnd = (int)Math.Ceiling(dataLen / (float)MTU);
|
||||||
|
dp.revderHash = new byte[dp.revderFrameEnd];
|
||||||
|
}
|
||||||
|
if (dp.revderHash[serialNo] == 0)
|
||||||
|
{
|
||||||
|
dp.revderHashCount++;
|
||||||
|
dp.revderHash[serialNo] = 1;
|
||||||
|
Buffer.BlockCopy(segment, segment.Position, dp.revderBuffer, (int)(serialNo * MTU), segment.Count - segment.Position);
|
||||||
|
if (dp.revderHashCount >= dp.revderFrameEnd)
|
||||||
|
dp.finish = true;
|
||||||
|
}
|
||||||
|
while (revderDict.TryGetValue(revderPackage, out var dp1))
|
||||||
|
{
|
||||||
|
if (tick >= progressTick)
|
||||||
|
{
|
||||||
|
progressTick = tick + 1000;
|
||||||
|
if (dp.revderFrameEnd * MTU >= ProgressDataLen)
|
||||||
|
{
|
||||||
|
var progress = (dp.revderHashCount / (float)dp.revderFrameEnd) * 100f;
|
||||||
|
OnRevdProgress?.Invoke(new RTProgress(progress, (RTState)(progress >= 100f ? 3 : 1)));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!dp1.finish)
|
||||||
|
break;
|
||||||
|
revderQueue.Enqueue(dp1.revderBuffer);
|
||||||
|
revderDict.Remove(revderPackage);
|
||||||
|
revderPackage++;
|
||||||
|
dp1.revderBuffer = null;
|
||||||
|
dp1.revderHash = null;
|
||||||
|
dp1.revderHashCount = 0;
|
||||||
|
}
|
||||||
|
J: segment.SetPositionLength(0);
|
||||||
|
segment.WriteByte(Cmd.Ack);
|
||||||
|
segment.Write(package);
|
||||||
|
segment.Write(serialNo);
|
||||||
|
segment.Write(dataLen);
|
||||||
|
var bytes = segment.ToArray(true);
|
||||||
|
OnSender(bytes);
|
||||||
|
}
|
||||||
|
else if (flags == Cmd.Ack)
|
||||||
|
{
|
||||||
|
var package = segment.ReadUInt32();
|
||||||
|
var serialNo = segment.ReadInt32();
|
||||||
|
var dataLen = segment.ReadInt32();
|
||||||
|
if (senderDict.TryGetValue(package, out var dic))
|
||||||
|
{
|
||||||
|
if (dic.Remove(serialNo))
|
||||||
|
ackNumber++;
|
||||||
|
if (dic.Count <= 0)
|
||||||
|
senderDict.Remove(package);
|
||||||
|
if (tick >= progressTick)
|
||||||
|
{
|
||||||
|
progressTick = tick + 1000;
|
||||||
|
if (dataLen >= ProgressDataLen)
|
||||||
|
{
|
||||||
|
var progress = ((dic.Count * MTU) / (float)dataLen) * 100f;
|
||||||
|
OnSendProgress?.Invoke(new RTProgress(progress, (RTState)(progress >= 100f ? 3 : 1)));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
FastRetransmit(senderPackage);
|
||||||
|
}
|
||||||
|
else if (flags == Cmd.DAck)
|
||||||
|
{
|
||||||
|
var package = segment.ReadUInt32();
|
||||||
|
FastRetransmit(package);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
private bool FastRetransmit(uint package)
|
||||||
|
{
|
||||||
|
if (senderDict.TryGetValue(package, out var dict))
|
||||||
|
{
|
||||||
|
foreach (var sender in dict.Values)
|
||||||
|
{
|
||||||
|
if (tick >= sender.tick & currFlow < MTPS & currAck < ackNumber)
|
||||||
|
{
|
||||||
|
sender.tick = tick + RTO;
|
||||||
|
var count = sender.buffer.Length;
|
||||||
|
currFlow += count;
|
||||||
|
currAck++;
|
||||||
|
OnSender(sender.buffer);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
public bool HasSend()
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
public void Dispose()
|
||||||
|
{
|
||||||
|
lock (SyncRoot)
|
||||||
|
{
|
||||||
|
pushPackage = 0;
|
||||||
|
senderPackage = 0;
|
||||||
|
revderPackage = 0;
|
||||||
|
senderQueue.Clear();
|
||||||
|
revderQueue.Clear();
|
||||||
|
senderDict.Clear();
|
||||||
|
revderDict.Clear();
|
||||||
|
RemotePoint = null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
public override string ToString()
|
||||||
|
{
|
||||||
|
return $"{RemotePoint}";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,276 @@
|
||||||
|
namespace Net.Server
|
||||||
|
{
|
||||||
|
using Net.Share;
|
||||||
|
using global::System;
|
||||||
|
using global::System.Net;
|
||||||
|
using global::System.Net.Sockets;
|
||||||
|
using global::System.Threading;
|
||||||
|
using Debug = Event.NDebug;
|
||||||
|
using Net.System;
|
||||||
|
using global::System.Security.Cryptography;
|
||||||
|
using Net.Helper;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// TCP服务器类型
|
||||||
|
/// 第三版本 2020.9.14
|
||||||
|
/// <para>Player:当有客户端连接服务器就会创建一个Player对象出来, Player对象和XXXClient是对等端, 每当有数据处理都会通知Player对象. </para>
|
||||||
|
/// <para>Scene:你可以定义自己的场景类型, 比如帧同步场景处理, mmorpg场景什么处理, 可以重写Scene的Update等等方法实现每个场景的更新和处理. </para>
|
||||||
|
/// </summary>
|
||||||
|
public class TcpServer<Player, Scene> : ServerBase<Player, Scene> where Player : NetPlayer, new() where Scene : NetScene<Player>, new()
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// tcp数据长度(4) + 1CRC协议 = 5
|
||||||
|
/// </summary>
|
||||||
|
protected override byte frame { get; set; } = 5;
|
||||||
|
public override bool MD5CRC
|
||||||
|
{
|
||||||
|
get => md5crc;
|
||||||
|
set
|
||||||
|
{
|
||||||
|
md5crc = value;
|
||||||
|
frame = (byte)(value ? 5 + 16 : 5);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
public override int HeartInterval { get; set; } = 1000 * 60 * 10;//10分钟跳一次
|
||||||
|
public override byte HeartLimit { get; set; } = 2;//确认两次
|
||||||
|
|
||||||
|
protected override void CreateOtherThread()
|
||||||
|
{
|
||||||
|
var thread = new Thread(ProcessAcceptConnect) { IsBackground = true, Name = "ProcessAcceptConnect" };
|
||||||
|
thread.Start();
|
||||||
|
threads.Add("ProcessAcceptConnect", thread);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override void CreateServerSocket(ushort port)
|
||||||
|
{
|
||||||
|
var ip = new IPEndPoint(IPAddress.Any, port);
|
||||||
|
Server = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
|
||||||
|
Server.NoDelay = true;
|
||||||
|
Server.Bind(ip);
|
||||||
|
Server.Listen(LineUp);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override void StartSocketHandler()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
private void ProcessAcceptConnect()
|
||||||
|
{
|
||||||
|
var acceptList = new FastList<Socket>();
|
||||||
|
while (IsRunServer)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
if (Server.Poll(0, SelectMode.SelectRead))
|
||||||
|
{
|
||||||
|
var socket = Server.Accept();
|
||||||
|
socket.ReceiveTimeout = 10000;
|
||||||
|
acceptList.Add(socket);
|
||||||
|
}
|
||||||
|
else Thread.Sleep(1);
|
||||||
|
CheckAcceptList(acceptList);
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
Debug.LogError($"接受异常:{ex}");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void CheckAcceptList(FastList<Socket> acceptList)
|
||||||
|
{
|
||||||
|
Socket client;
|
||||||
|
for (int i = 0; i < acceptList.Count; i++)
|
||||||
|
{
|
||||||
|
client = acceptList[i];
|
||||||
|
if (!client.Connected)
|
||||||
|
{
|
||||||
|
client.Close();
|
||||||
|
acceptList.RemoveAt(i);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (client.Poll(0, SelectMode.SelectRead))
|
||||||
|
{
|
||||||
|
using (var segment = BufferPool.Take())
|
||||||
|
{
|
||||||
|
segment.Count = client.Receive(segment, 0, segment.Length, SocketFlags.None, out var error);
|
||||||
|
if (segment.Count == 0 | error != SocketError.Success) //当等待10秒超时
|
||||||
|
{
|
||||||
|
client.Close();
|
||||||
|
acceptList.RemoveAt(i);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
client.ReceiveTimeout = 0;
|
||||||
|
var userID = segment.ReadInt32();
|
||||||
|
if (!UIDClients.TryGetValue(userID, out var client1))
|
||||||
|
{
|
||||||
|
client1 = AcceptHander(client, client.RemoteEndPoint);
|
||||||
|
goto J;
|
||||||
|
}
|
||||||
|
if (!client1.Client.Connected) //防止出错或者假冒的客户端设置, 导致直接替换真实的客户端
|
||||||
|
{
|
||||||
|
client1.Client = client;
|
||||||
|
SetClientIdentity(client1);
|
||||||
|
client1.OnReconnecting();
|
||||||
|
OnReconnecting(client1);
|
||||||
|
}
|
||||||
|
else AcceptHander(client, client.RemoteEndPoint);//如果取出的客户端不断线, 那说明是客户端有问题或者错乱, 给他个新的连接
|
||||||
|
J: acceptList.RemoveAt(i);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override void OnThreadQueueSet(Player client)
|
||||||
|
{
|
||||||
|
var value = threadNum++;
|
||||||
|
client.Group = ThreadGroups[value % ThreadGroups.Count];
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override void OnSceneGroupSet(Scene scene)
|
||||||
|
{
|
||||||
|
var value = threadNum++;
|
||||||
|
scene.Group = ThreadGroups[value % ThreadGroups.Count];
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override void ResolveDataQueue(Player client, ref bool isSleep, uint tick)
|
||||||
|
{
|
||||||
|
if (!client.Client.Connected) //当socket断开后, 需要重连, 所以会等待一段重连时间
|
||||||
|
{
|
||||||
|
if (tick >= client.ReconnectTimeout)
|
||||||
|
RemoveClient(client);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (client.Client.Poll(0, SelectMode.SelectRead))
|
||||||
|
{
|
||||||
|
var segment = BufferPool.Take();
|
||||||
|
segment.Count = client.Client.Receive(segment, 0, segment.Length, SocketFlags.None, out SocketError error);
|
||||||
|
if (segment.Count == 0 | error != SocketError.Success)
|
||||||
|
{
|
||||||
|
BufferPool.Push(segment);
|
||||||
|
client.Client.Disconnect(false);//标记为断开状态
|
||||||
|
client.ReconnectTimeout = tick + ReconnectionTimeout;
|
||||||
|
client.OnConnectLost();
|
||||||
|
OnConnectLost(client);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
receiveCount += segment.Count;
|
||||||
|
receiveAmount++;
|
||||||
|
ResolveBuffer(client, ref segment);
|
||||||
|
BufferPool.Push(segment);
|
||||||
|
isSleep = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override void ReceiveProcessed(EndPoint remotePoint, ref bool isSleep)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override bool IsInternalCommand(Player client, RPCModel model)
|
||||||
|
{
|
||||||
|
if (model.cmd == NetCmd.Connect | model.cmd == NetCmd.Broadcast)
|
||||||
|
return true;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override byte[] PackData(Segment stream)
|
||||||
|
{
|
||||||
|
stream.Flush();
|
||||||
|
if (MD5CRC)
|
||||||
|
{
|
||||||
|
MD5 md5 = new MD5CryptoServiceProvider();
|
||||||
|
var head = frame;
|
||||||
|
byte[] retVal = md5.ComputeHash(stream, head, stream.Count - head);
|
||||||
|
EncryptHelper.ToEncrypt(Password, retVal);
|
||||||
|
int len = stream.Count - head;
|
||||||
|
var lenBytes = BitConverter.GetBytes(len);
|
||||||
|
byte crc = CRCHelper.CRC8(lenBytes, 0, lenBytes.Length);
|
||||||
|
stream.Position = 0;
|
||||||
|
stream.Write(lenBytes, 0, 4);
|
||||||
|
stream.WriteByte(crc);
|
||||||
|
stream.Write(retVal, 0, retVal.Length);
|
||||||
|
stream.Position = len + head;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
int len = stream.Count - frame;
|
||||||
|
var lenBytes = BitConverter.GetBytes(len);
|
||||||
|
byte crc = CRCHelper.CRC8(lenBytes, 0, lenBytes.Length);
|
||||||
|
stream.Position = 0;
|
||||||
|
stream.Write(lenBytes, 0, 4);
|
||||||
|
stream.WriteByte(crc);
|
||||||
|
stream.Position = len + frame;
|
||||||
|
}
|
||||||
|
return stream.ToArray();
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override void SendRTDataHandle(Player client, QueueSafe<RPCModel> rtRPCModels)
|
||||||
|
{
|
||||||
|
SendDataHandle(client, rtRPCModels, true);
|
||||||
|
}
|
||||||
|
#if TEST1
|
||||||
|
ListSafe<byte> list = new ListSafe<byte>();
|
||||||
|
#endif
|
||||||
|
protected override void SendByteData(Player client, byte[] buffer, bool reliable)
|
||||||
|
{
|
||||||
|
if (!client.Client.Connected)
|
||||||
|
return;
|
||||||
|
if (buffer.Length <= frame)//解决长度==6的问题(没有数据)
|
||||||
|
return;
|
||||||
|
if (client.Client.Poll(1, SelectMode.SelectWrite))
|
||||||
|
{
|
||||||
|
#if TEST1
|
||||||
|
list.AddRange(buffer);
|
||||||
|
do
|
||||||
|
{
|
||||||
|
var buffer1 = list.GetRemoveRange(0, RandomHelper.Range(0, buffer.Length));
|
||||||
|
Net.Client.ClientBase.Instance.ReceiveTest(buffer1);
|
||||||
|
}
|
||||||
|
while (client.tcpRPCModels.Count == 0 & list.Count > 0);
|
||||||
|
#else
|
||||||
|
int count1 = client.Client.Send(buffer, 0, buffer.Length, SocketFlags.None, out SocketError error);
|
||||||
|
if (error != SocketError.Success | count1 <= 0)
|
||||||
|
{
|
||||||
|
OnSendErrorHandle?.Invoke(client, buffer, true);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
else if (count1 != buffer.Length)
|
||||||
|
Debug.Log($"发送了{buffer.Length - count1}个字节失败!");
|
||||||
|
sendAmount++;
|
||||||
|
sendCount += buffer.Length;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Debug.LogError($"[{client}]发送缓冲列表已经超出限制!");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override void CheckHeart(Player client, uint tick)
|
||||||
|
{
|
||||||
|
if (!client.Client.Connected)
|
||||||
|
{
|
||||||
|
if (tick >= client.ReconnectTimeout)
|
||||||
|
RemoveClient(client);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (client.heart > HeartLimit * 5)
|
||||||
|
{
|
||||||
|
client.Redundant = true;
|
||||||
|
RemoveClient(client);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
client.heart++;
|
||||||
|
if (client.heart <= HeartLimit)//确认心跳包
|
||||||
|
return;
|
||||||
|
SendRT(client, NetCmd.SendHeartbeat, new byte[0]);//保活连接状态
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 默认tcp服务器,当不需要处理Player对象和Scene对象时可使用
|
||||||
|
/// </summary>
|
||||||
|
public class TcpServer : TcpServer<NetPlayer, DefaultScene>
|
||||||
|
{
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,115 @@
|
||||||
|
namespace Net.Server
|
||||||
|
{
|
||||||
|
using Net.Share;
|
||||||
|
using global::System;
|
||||||
|
using global::System.Collections.Generic;
|
||||||
|
using global::System.Net;
|
||||||
|
using global::System.Net.Sockets;
|
||||||
|
using global::System.Threading;
|
||||||
|
using Debug = Event.NDebug;
|
||||||
|
using Net.System;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// tcp 输入输出完成端口服务器
|
||||||
|
/// <para>Player:当有客户端连接服务器就会创建一个Player对象出来, Player对象和XXXClient是对等端, 每当有数据处理都会通知Player对象. </para>
|
||||||
|
/// <para>Scene:你可以定义自己的场景类型, 比如帧同步场景处理, mmorpg场景什么处理, 可以重写Scene的Update等等方法实现每个场景的更新和处理. </para>
|
||||||
|
/// </summary>
|
||||||
|
public class TcpServerIocp<Player, Scene> : TcpServer<Player, Scene> where Player : NetPlayer, new() where Scene : NetScene<Player>, new()
|
||||||
|
{
|
||||||
|
protected override void StartSocketHandler()
|
||||||
|
{
|
||||||
|
AcceptHandler();
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override void CreateServerSocket(ushort port)
|
||||||
|
{
|
||||||
|
Server = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
|
||||||
|
var ip = new IPEndPoint(IPAddress.Any, port);
|
||||||
|
Server.NoDelay = true;
|
||||||
|
Server.Bind(ip);
|
||||||
|
Server.Listen(LineUp);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void AcceptHandler()
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
if (!IsRunServer)
|
||||||
|
return;
|
||||||
|
if (ServerArgs == null)
|
||||||
|
{
|
||||||
|
ServerArgs = new SocketAsyncEventArgs();
|
||||||
|
ServerArgs.Completed += OnIOCompleted;
|
||||||
|
}
|
||||||
|
ServerArgs.AcceptSocket = null;// 重用前进行对象清理
|
||||||
|
if (!Server.AcceptAsync(ServerArgs))
|
||||||
|
OnIOCompleted(null, ServerArgs);
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
Debug.Log($"接受异常:{ex}");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override void OnIOCompleted(object sender, SocketAsyncEventArgs args)
|
||||||
|
{
|
||||||
|
Socket clientSocket = null;
|
||||||
|
switch (args.LastOperation)
|
||||||
|
{
|
||||||
|
case SocketAsyncOperation.Accept:
|
||||||
|
try
|
||||||
|
{
|
||||||
|
clientSocket = args.AcceptSocket;
|
||||||
|
if (clientSocket.RemoteEndPoint == null)
|
||||||
|
return;
|
||||||
|
var client = AcceptHander(clientSocket, clientSocket.RemoteEndPoint);
|
||||||
|
client.ReceiveArgs = new SocketAsyncEventArgs();
|
||||||
|
client.ReceiveArgs.UserToken = client;
|
||||||
|
client.ReceiveArgs.RemoteEndPoint = clientSocket.RemoteEndPoint;
|
||||||
|
client.ReceiveArgs.SetBuffer(new byte[ushort.MaxValue], 0, ushort.MaxValue);
|
||||||
|
client.ReceiveArgs.Completed += OnIOCompleted;
|
||||||
|
if (!clientSocket.ReceiveAsync(client.ReceiveArgs))
|
||||||
|
OnIOCompleted(null, client.ReceiveArgs);
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
Debug.LogError(ex.ToString());
|
||||||
|
}
|
||||||
|
finally
|
||||||
|
{
|
||||||
|
AcceptHandler();
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case SocketAsyncOperation.Receive:
|
||||||
|
var client1 = args.UserToken as Player;
|
||||||
|
int count = args.BytesTransferred;
|
||||||
|
if (count > 0 & args.SocketError == SocketError.Success)
|
||||||
|
{
|
||||||
|
var buffer = BufferPool.Take();
|
||||||
|
buffer.Count = count;
|
||||||
|
Buffer.BlockCopy(args.Buffer, args.Offset, buffer, 0, count);
|
||||||
|
receiveCount += count;
|
||||||
|
receiveAmount++;
|
||||||
|
if (client1.isDispose)
|
||||||
|
{
|
||||||
|
BufferPool.Push(buffer);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
ResolveBuffer(client1, ref buffer);
|
||||||
|
BufferPool.Push(buffer);
|
||||||
|
clientSocket = client1.Client;
|
||||||
|
if (!clientSocket.Connected)
|
||||||
|
return;
|
||||||
|
if (!clientSocket.ReceiveAsync(args))
|
||||||
|
OnIOCompleted(null, args);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 默认tcpiocp服务器,当不需要处理Player对象和Scene对象时可使用
|
||||||
|
/// </summary>
|
||||||
|
public class TcpServerIocp : TcpServerIocp<NetPlayer, DefaultScene> { }
|
||||||
|
}
|
|
@ -0,0 +1,99 @@
|
||||||
|
namespace Net.Server
|
||||||
|
{
|
||||||
|
using Net.Share;
|
||||||
|
using global::System;
|
||||||
|
using global::System.Net;
|
||||||
|
using global::System.Net.Sockets;
|
||||||
|
using global::System.Threading;
|
||||||
|
using Debug = Event.NDebug;
|
||||||
|
using Net.System;
|
||||||
|
using Net.Event;
|
||||||
|
using global::System.Linq;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Udp网络服务器
|
||||||
|
/// <para>Player:当有客户端连接服务器就会创建一个Player对象出来, Player对象和XXXClient是对等端, 每当有数据处理都会通知Player对象. </para>
|
||||||
|
/// <para>Scene:你可以定义自己的场景类型, 比如帧同步场景处理, mmorpg场景什么处理, 可以重写Scene的Update等等方法实现每个场景的更新和处理. </para>
|
||||||
|
/// </summary>
|
||||||
|
public class UdpServer<Player, Scene> : ServerBase<Player, Scene> where Player : NetPlayer, new() where Scene : NetScene<Player>, new()
|
||||||
|
{
|
||||||
|
protected override void CreateServerSocket(ushort port)
|
||||||
|
{
|
||||||
|
Server = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp);
|
||||||
|
IPEndPoint ip = new IPEndPoint(IPAddress.Any, port);
|
||||||
|
Server.Bind(ip);
|
||||||
|
#if !UNITY_ANDROID && WINDOWS//在安卓启动服务器时忽略此错误
|
||||||
|
uint IOC_IN = 0x80000000;
|
||||||
|
uint IOC_VENDOR = 0x18000000;
|
||||||
|
uint SIO_UDP_CONNRESET = IOC_IN | IOC_VENDOR | 12;
|
||||||
|
Server.IOControl((int)SIO_UDP_CONNRESET, new byte[] { Convert.ToByte(false) }, null);//udp远程关闭现有连接方案
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override void OnThreadQueueSet(Player client)
|
||||||
|
{
|
||||||
|
client.Group = ThreadGroupDict[Thread.CurrentThread.ManagedThreadId];
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override void AcceptHander(Player client)
|
||||||
|
{
|
||||||
|
client.Gcp = new Plugins.GcpKernel();
|
||||||
|
client.Gcp.MTU = (ushort)MTU;
|
||||||
|
client.Gcp.RTO = RTO;
|
||||||
|
client.Gcp.MTPS = MTPS;
|
||||||
|
client.Gcp.FlowControl = FlowControl;
|
||||||
|
client.Gcp.RemotePoint = client.RemotePoint;
|
||||||
|
client.Gcp.OnSender += (bytes) => {
|
||||||
|
Send(client, NetCmd.ReliableTransport, bytes);
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 默认udp服务器,当不需要处理Player对象和Scene对象时可使用
|
||||||
|
/// </summary>
|
||||||
|
public class UdpServer : UdpServer<NetPlayer, DefaultScene>
|
||||||
|
{
|
||||||
|
#if UDPTEST
|
||||||
|
protected override void ProcessReceive()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
internal void ReceiveTest(byte[] bytes, EndPoint remotePoint)
|
||||||
|
{
|
||||||
|
var buffer = new Segment(bytes, false);
|
||||||
|
receiveCount += buffer.Count;
|
||||||
|
receiveAmount++;
|
||||||
|
ReceiveProcessed(remotePoint, buffer, false);
|
||||||
|
}
|
||||||
|
internal void DataHandlerTest(byte[] bytes, EndPoint remotePoint)
|
||||||
|
{
|
||||||
|
DataHandle(AllClients[remotePoint], bytes);
|
||||||
|
}
|
||||||
|
protected override void SendByteData(NetPlayer client, byte[] buffer, bool reliable)
|
||||||
|
{
|
||||||
|
if (buffer.Length == frame)//解决长度==6的问题(没有数据)
|
||||||
|
return;
|
||||||
|
if (buffer.Length >= 65507)
|
||||||
|
{
|
||||||
|
Debug.LogError($"[{client}] 数据太大! 请使用SendRT");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
(Net.Client.UdpClient.Instance as Net.Client.UdpClient).ReceiveTest(buffer);
|
||||||
|
sendAmount++;
|
||||||
|
sendCount += buffer.Length;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gcp网络服务器
|
||||||
|
/// <para>Player:当有客户端连接服务器就会创建一个Player对象出来, Player对象和XXXClient是对等端, 每当有数据处理都会通知Player对象. </para>
|
||||||
|
/// <para>Scene:你可以定义自己的场景类型, 比如帧同步场景处理, mmorpg场景什么处理, 可以重写Scene的Update等等方法实现每个场景的更新和处理. </para>
|
||||||
|
/// </summary>
|
||||||
|
public class GcpServer<Player, Scene> : UdpServer<Player, Scene> where Player : NetPlayer, new() where Scene : NetScene<Player>, new() { }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 默认gcp服务器,当不需要处理Player对象和Scene对象时可使用
|
||||||
|
/// </summary>
|
||||||
|
public class GcpServer : GcpServer<NetPlayer, DefaultScene> { }
|
||||||
|
}
|
|
@ -0,0 +1,71 @@
|
||||||
|
using Net.Event;
|
||||||
|
using Net.Share;
|
||||||
|
using Net.System;
|
||||||
|
using System;
|
||||||
|
using System.Net.Sockets;
|
||||||
|
using System.Threading;
|
||||||
|
|
||||||
|
namespace Net.Server
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// udp 输入输出完成端口服务器
|
||||||
|
/// <para>Player:当有客户端连接服务器就会创建一个Player对象出来, Player对象和XXXClient是对等端, 每当有数据处理都会通知Player对象. </para>
|
||||||
|
/// <para>Scene:你可以定义自己的场景类型, 比如帧同步场景处理, mmorpg场景什么处理, 可以重写Scene的Update等等方法实现每个场景的更新和处理. </para>
|
||||||
|
/// </summary>
|
||||||
|
/// <typeparam name="Player"></typeparam>
|
||||||
|
/// <typeparam name="Scene"></typeparam>
|
||||||
|
public class UdpServerIocp<Player, Scene> : ServerBase<Player, Scene> where Player : NetPlayer, new() where Scene : NetScene<Player>, new()
|
||||||
|
{
|
||||||
|
protected override void StartSocketHandler()
|
||||||
|
{
|
||||||
|
ServerArgs = new SocketAsyncEventArgs { UserToken = Server };
|
||||||
|
ServerArgs.Completed += OnIOCompleted;
|
||||||
|
ServerArgs.SetBuffer(new byte[ushort.MaxValue], 0, ushort.MaxValue);
|
||||||
|
ServerArgs.RemoteEndPoint = Server.LocalEndPoint;
|
||||||
|
if (!Server.ReceiveFromAsync(ServerArgs))
|
||||||
|
OnIOCompleted(null, ServerArgs);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override void AcceptHander(Player client)
|
||||||
|
{
|
||||||
|
client.Gcp = new Plugins.GcpKernel();
|
||||||
|
client.Gcp.MTU = (ushort)MTU;
|
||||||
|
client.Gcp.RTO = RTO;
|
||||||
|
client.Gcp.MTPS = MTPS;
|
||||||
|
client.Gcp.FlowControl = FlowControl;
|
||||||
|
client.Gcp.RemotePoint = client.RemotePoint;
|
||||||
|
client.Gcp.OnSender += (bytes) => {
|
||||||
|
Send(client, NetCmd.ReliableTransport, bytes);
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
protected unsafe override void SendByteData(Player client, byte[] buffer, bool reliable)
|
||||||
|
{
|
||||||
|
if (buffer.Length == frame)//解决长度==6的问题(没有数据)
|
||||||
|
return;
|
||||||
|
if (buffer.Length >= 65507)
|
||||||
|
{
|
||||||
|
NDebug.LogError($"[{client}] 数据太大! 请使用SendRT");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
var args = ObjectPool<SocketAsyncEventArgs>.Take(args1 =>
|
||||||
|
{
|
||||||
|
args1.Completed += OnIOCompleted;
|
||||||
|
args1.SetBuffer(new byte[ushort.MaxValue], 0, ushort.MaxValue);
|
||||||
|
});
|
||||||
|
args.RemoteEndPoint = client.RemotePoint;
|
||||||
|
var buffer1 = args.Buffer;
|
||||||
|
Buffer.BlockCopy(buffer, 0, buffer1, 0, buffer.Length);
|
||||||
|
args.SetBuffer(0, buffer.Length);
|
||||||
|
if (!Server.SendToAsync(args))
|
||||||
|
OnIOCompleted(client, args);
|
||||||
|
sendAmount++;
|
||||||
|
sendCount += buffer.Length;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 默认udpiocp服务器,当不需要处理Player对象和Scene对象时可使用
|
||||||
|
/// </summary>
|
||||||
|
public class UdpServerIocp : UdpServerIocp<NetPlayer, DefaultScene> { }
|
||||||
|
}
|
|
@ -243,7 +243,7 @@ namespace Utilities.AssetsCache
|
||||||
|
|
||||||
private void ResizeScrollView()
|
private void ResizeScrollView()
|
||||||
{
|
{
|
||||||
GUI.DrawTexture(_cursorChangeRect, null);
|
//GUI.DrawTexture(_cursorChangeRect, null);
|
||||||
EditorGUIUtility.AddCursorRect(_cursorChangeRect, MouseCursor.ResizeHorizontal);
|
EditorGUIUtility.AddCursorRect(_cursorChangeRect, MouseCursor.ResizeHorizontal);
|
||||||
|
|
||||||
if (Event.current.type == EventType.MouseDown && _cursorChangeRect.Contains(Event.current.mousePosition))
|
if (Event.current.type == EventType.MouseDown && _cursorChangeRect.Contains(Event.current.mousePosition))
|
||||||
|
|
|
@ -1 +1 @@
|
||||||
{"savePath":"D:/Users/Iris/wkspaces/BitFall_CubeSquard/Assets/Scripts/FastBinrayGenerate","typeNames":[{"name":"Unity.Mathematics.float3","foldout":true,"fields":[{"name":"x","serialize":true,"select":0},{"name":"y","serialize":true,"select":0},{"name":"z","serialize":true,"select":0},{"name":"xyz","serialize":false,"select":0},{"name":"xzy","serialize":false,"select":0},{"name":"yxz","serialize":false,"select":0},{"name":"yzx","serialize":false,"select":0},{"name":"zxy","serialize":false,"select":0},{"name":"zyx","serialize":false,"select":0},{"name":"xy","serialize":false,"select":0},{"name":"xz","serialize":false,"select":0},{"name":"yx","serialize":false,"select":0},{"name":"yz","serialize":false,"select":0},{"name":"zx","serialize":false,"select":0},{"name":"zy","serialize":false,"select":0}]}],"typeEntry":null,"methodEntry":null,"showType":0,"searchAssemblies":"Unity.Mathematics"}
|
{"savePath":"D:/Iris/Documents/GitHub/BITFALL-Runtime/Packages/Runtime~/Generate/FastBinary2","typeNames":[{"name":"BITFALL.Services.PlayerModel","foldout":true,"fields":[{"name":"Id","serialize":true,"select":0},{"name":"Name","serialize":true,"select":0},{"name":"SteamId","serialize":true,"select":0}]},{"name":"BITFALL.Services.VerifyPlayerCommand","foldout":true,"fields":[{"name":"PlayerModel","serialize":true,"select":0}]},{"name":"BITFALL.Services.PlayerVerifiedCommand","foldout":true,"fields":[{"name":"PlayerModel","serialize":true,"select":0}]}],"typeEntry":null,"methodEntry":null,"showType":0,"searchAssemblies":"BITFALL.Player.Core"}
|