[Add] FishNet
This commit is contained in:
+1776
File diff suppressed because it is too large
Load Diff
+15
@@ -0,0 +1,15 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 941f6f8cbac7e9d418ffc6f22ee9359f
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
AssetOrigin:
|
||||
serializedVersion: 1
|
||||
productId: 207815
|
||||
packageName: 'FishNet: Networking Evolved'
|
||||
packageVersion: 4.6.22R
|
||||
assetPath: Assets/FishNet/Demos/Prediction/CharacterController/CharacterController
|
||||
Prediction Demo.unity
|
||||
uploadId: 866910
|
||||
@@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: bdae6fa333d2d94449c27856e21d936a
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,80 @@
|
||||
%YAML 1.1
|
||||
%TAG !u! tag:unity3d.com,2011:
|
||||
--- !u!21 &2100000
|
||||
Material:
|
||||
serializedVersion: 8
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_Name: BlueMat
|
||||
m_Shader: {fileID: 46, guid: 0000000000000000f000000000000000, type: 0}
|
||||
m_ValidKeywords: []
|
||||
m_InvalidKeywords: []
|
||||
m_LightmapFlags: 4
|
||||
m_EnableInstancingVariants: 0
|
||||
m_DoubleSidedGI: 0
|
||||
m_CustomRenderQueue: -1
|
||||
stringTagMap: {}
|
||||
disabledShaderPasses: []
|
||||
m_SavedProperties:
|
||||
serializedVersion: 3
|
||||
m_TexEnvs:
|
||||
- _BumpMap:
|
||||
m_Texture: {fileID: 0}
|
||||
m_Scale: {x: 1, y: 1}
|
||||
m_Offset: {x: 0, y: 0}
|
||||
- _DetailAlbedoMap:
|
||||
m_Texture: {fileID: 0}
|
||||
m_Scale: {x: 1, y: 1}
|
||||
m_Offset: {x: 0, y: 0}
|
||||
- _DetailMask:
|
||||
m_Texture: {fileID: 0}
|
||||
m_Scale: {x: 1, y: 1}
|
||||
m_Offset: {x: 0, y: 0}
|
||||
- _DetailNormalMap:
|
||||
m_Texture: {fileID: 0}
|
||||
m_Scale: {x: 1, y: 1}
|
||||
m_Offset: {x: 0, y: 0}
|
||||
- _EmissionMap:
|
||||
m_Texture: {fileID: 0}
|
||||
m_Scale: {x: 1, y: 1}
|
||||
m_Offset: {x: 0, y: 0}
|
||||
- _MainTex:
|
||||
m_Texture: {fileID: 0}
|
||||
m_Scale: {x: 1, y: 1}
|
||||
m_Offset: {x: 0, y: 0}
|
||||
- _MetallicGlossMap:
|
||||
m_Texture: {fileID: 0}
|
||||
m_Scale: {x: 1, y: 1}
|
||||
m_Offset: {x: 0, y: 0}
|
||||
- _OcclusionMap:
|
||||
m_Texture: {fileID: 0}
|
||||
m_Scale: {x: 1, y: 1}
|
||||
m_Offset: {x: 0, y: 0}
|
||||
- _ParallaxMap:
|
||||
m_Texture: {fileID: 0}
|
||||
m_Scale: {x: 1, y: 1}
|
||||
m_Offset: {x: 0, y: 0}
|
||||
m_Ints: []
|
||||
m_Floats:
|
||||
- _BumpScale: 1
|
||||
- _Cutoff: 0.5
|
||||
- _DetailNormalMapScale: 1
|
||||
- _DstBlend: 0
|
||||
- _GlossMapScale: 1
|
||||
- _Glossiness: 0.5
|
||||
- _GlossyReflections: 1
|
||||
- _Metallic: 0
|
||||
- _Mode: 0
|
||||
- _OcclusionStrength: 1
|
||||
- _Parallax: 0.02
|
||||
- _SmoothnessTextureChannel: 0
|
||||
- _SpecularHighlights: 1
|
||||
- _SrcBlend: 1
|
||||
- _UVSec: 0
|
||||
- _ZWrite: 1
|
||||
m_Colors:
|
||||
- _Color: {r: 0, g: 0.363446, b: 0.5471698, a: 1}
|
||||
- _EmissionColor: {r: 0, g: 0, b: 0, a: 1}
|
||||
m_BuildTextureStacks: []
|
||||
@@ -0,0 +1,15 @@
|
||||
fileFormatVersion: 2
|
||||
guid: a2ca0973c8f8a4846bb7f3894c3bc5cf
|
||||
NativeFormatImporter:
|
||||
externalObjects: {}
|
||||
mainObjectFileID: 2100000
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
AssetOrigin:
|
||||
serializedVersion: 1
|
||||
productId: 207815
|
||||
packageName: 'FishNet: Networking Evolved'
|
||||
packageVersion: 4.6.22R
|
||||
assetPath: Assets/FishNet/Demos/Prediction/CharacterController/Materials/BlueMat.mat
|
||||
uploadId: 866910
|
||||
@@ -0,0 +1,80 @@
|
||||
%YAML 1.1
|
||||
%TAG !u! tag:unity3d.com,2011:
|
||||
--- !u!21 &2100000
|
||||
Material:
|
||||
serializedVersion: 8
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_Name: OrangeMat
|
||||
m_Shader: {fileID: 46, guid: 0000000000000000f000000000000000, type: 0}
|
||||
m_ValidKeywords: []
|
||||
m_InvalidKeywords: []
|
||||
m_LightmapFlags: 4
|
||||
m_EnableInstancingVariants: 0
|
||||
m_DoubleSidedGI: 0
|
||||
m_CustomRenderQueue: -1
|
||||
stringTagMap: {}
|
||||
disabledShaderPasses: []
|
||||
m_SavedProperties:
|
||||
serializedVersion: 3
|
||||
m_TexEnvs:
|
||||
- _BumpMap:
|
||||
m_Texture: {fileID: 0}
|
||||
m_Scale: {x: 1, y: 1}
|
||||
m_Offset: {x: 0, y: 0}
|
||||
- _DetailAlbedoMap:
|
||||
m_Texture: {fileID: 0}
|
||||
m_Scale: {x: 1, y: 1}
|
||||
m_Offset: {x: 0, y: 0}
|
||||
- _DetailMask:
|
||||
m_Texture: {fileID: 0}
|
||||
m_Scale: {x: 1, y: 1}
|
||||
m_Offset: {x: 0, y: 0}
|
||||
- _DetailNormalMap:
|
||||
m_Texture: {fileID: 0}
|
||||
m_Scale: {x: 1, y: 1}
|
||||
m_Offset: {x: 0, y: 0}
|
||||
- _EmissionMap:
|
||||
m_Texture: {fileID: 0}
|
||||
m_Scale: {x: 1, y: 1}
|
||||
m_Offset: {x: 0, y: 0}
|
||||
- _MainTex:
|
||||
m_Texture: {fileID: 0}
|
||||
m_Scale: {x: 1, y: 1}
|
||||
m_Offset: {x: 0, y: 0}
|
||||
- _MetallicGlossMap:
|
||||
m_Texture: {fileID: 0}
|
||||
m_Scale: {x: 1, y: 1}
|
||||
m_Offset: {x: 0, y: 0}
|
||||
- _OcclusionMap:
|
||||
m_Texture: {fileID: 0}
|
||||
m_Scale: {x: 1, y: 1}
|
||||
m_Offset: {x: 0, y: 0}
|
||||
- _ParallaxMap:
|
||||
m_Texture: {fileID: 0}
|
||||
m_Scale: {x: 1, y: 1}
|
||||
m_Offset: {x: 0, y: 0}
|
||||
m_Ints: []
|
||||
m_Floats:
|
||||
- _BumpScale: 1
|
||||
- _Cutoff: 0.5
|
||||
- _DetailNormalMapScale: 1
|
||||
- _DstBlend: 0
|
||||
- _GlossMapScale: 1
|
||||
- _Glossiness: 0.5
|
||||
- _GlossyReflections: 1
|
||||
- _Metallic: 0
|
||||
- _Mode: 0
|
||||
- _OcclusionStrength: 1
|
||||
- _Parallax: 0.02
|
||||
- _SmoothnessTextureChannel: 0
|
||||
- _SpecularHighlights: 1
|
||||
- _SrcBlend: 1
|
||||
- _UVSec: 0
|
||||
- _ZWrite: 1
|
||||
m_Colors:
|
||||
- _Color: {r: 1, g: 0.4404881, b: 0, a: 1}
|
||||
- _EmissionColor: {r: 0, g: 0, b: 0, a: 1}
|
||||
m_BuildTextureStacks: []
|
||||
@@ -0,0 +1,15 @@
|
||||
fileFormatVersion: 2
|
||||
guid: f04f4c9957a2bf340b9fea1547c7ce0b
|
||||
NativeFormatImporter:
|
||||
externalObjects: {}
|
||||
mainObjectFileID: 2100000
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
AssetOrigin:
|
||||
serializedVersion: 1
|
||||
productId: 207815
|
||||
packageName: 'FishNet: Networking Evolved'
|
||||
packageVersion: 4.6.22R
|
||||
assetPath: Assets/FishNet/Demos/Prediction/CharacterController/Materials/OrangeMat.mat
|
||||
uploadId: 866910
|
||||
@@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 50d54accc2af0c746b0729b097981b93
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
+330
@@ -0,0 +1,330 @@
|
||||
%YAML 1.1
|
||||
%TAG !u! tag:unity3d.com,2011:
|
||||
--- !u!1 &303449598114786579
|
||||
GameObject:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
serializedVersion: 6
|
||||
m_Component:
|
||||
- component: {fileID: 303449598114786577}
|
||||
- component: {fileID: -2060332294883903109}
|
||||
- component: {fileID: 201277550}
|
||||
- component: {fileID: 4148834954576211901}
|
||||
- component: {fileID: 8534672635240368605}
|
||||
m_Layer: 0
|
||||
m_Name: CharacterControllerPrediction
|
||||
m_TagString: Untagged
|
||||
m_Icon: {fileID: 0}
|
||||
m_NavMeshLayer: 0
|
||||
m_StaticEditorFlags: 0
|
||||
m_IsActive: 1
|
||||
--- !u!4 &303449598114786577
|
||||
Transform:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 303449598114786579}
|
||||
m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
|
||||
m_LocalPosition: {x: -4.80351, y: 0.18147132, z: 5.430528}
|
||||
m_LocalScale: {x: 1, y: 1, z: 1}
|
||||
m_ConstrainProportionsScale: 0
|
||||
m_Children:
|
||||
- {fileID: 6952090537135875148}
|
||||
- {fileID: 7416592246441027450}
|
||||
m_Father: {fileID: 0}
|
||||
m_RootOrder: 0
|
||||
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
|
||||
--- !u!114 &-2060332294883903109
|
||||
MonoBehaviour:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 303449598114786579}
|
||||
m_Enabled: 1
|
||||
m_EditorHideFlags: 0
|
||||
m_Script: {fileID: 11500000, guid: 53a6d84aa5d214e48a7308646e5d20da, type: 3}
|
||||
m_Name:
|
||||
m_EditorClassIdentifier:
|
||||
_componentIndexCache: 0
|
||||
_addedNetworkObject: {fileID: 201277550}
|
||||
_networkObjectCache: {fileID: 201277550}
|
||||
_tickCallbacks: 6
|
||||
_jumpForce: 13
|
||||
_moveRate: 4
|
||||
--- !u!114 &201277550
|
||||
MonoBehaviour:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 303449598114786579}
|
||||
m_Enabled: 1
|
||||
m_EditorHideFlags: 0
|
||||
m_Script: {fileID: 11500000, guid: 26b716c41e9b56b4baafaf13a523ba2e, type: 3}
|
||||
m_Name:
|
||||
m_EditorClassIdentifier:
|
||||
<IsNested>k__BackingField: 0
|
||||
WasActiveDuringEdit: 0
|
||||
WasActiveDuringEdit_Set1: 1
|
||||
<ComponentIndex>k__BackingField: 0
|
||||
<PredictedSpawn>k__BackingField: {fileID: 0}
|
||||
<PredictedOwner>k__BackingField: {fileID: 0}
|
||||
NetworkBehaviours:
|
||||
- {fileID: -2060332294883903109}
|
||||
- {fileID: 8022627623488540705}
|
||||
- {fileID: 2367975056509727580}
|
||||
InitializedParentNetworkBehaviour: {fileID: 0}
|
||||
InitializedNestedNetworkObjects: []
|
||||
RuntimeParentNetworkBehaviour: {fileID: 0}
|
||||
RuntimeChildNetworkBehaviours: []
|
||||
_isNetworked: 1
|
||||
_isSpawnable: 1
|
||||
_isGlobal: 0
|
||||
_initializeOrder: 0
|
||||
_preventDespawnOnDisconnect: 0
|
||||
_defaultDespawnType: 0
|
||||
_initializedTimestamp: -8584312066425166658
|
||||
NetworkObserver: {fileID: 0}
|
||||
_enablePrediction: 1
|
||||
_predictionType: 0
|
||||
_localReconcileCorrectionType: 2
|
||||
_graphicalObject: {fileID: 0}
|
||||
_detachGraphicalObject: 0
|
||||
_enableStateForwarding: 1
|
||||
_networkTransform: {fileID: 0}
|
||||
_ownerInterpolation: 2
|
||||
_ownerSmoothedProperties: 255
|
||||
_adaptiveInterpolation: 0
|
||||
_spectatorSmoothedProperties: 255
|
||||
_spectatorInterpolation: 2
|
||||
_enableTeleport: 0
|
||||
_teleportThreshold: 1
|
||||
<PrefabId>k__BackingField: 7
|
||||
<SpawnableCollectionId>k__BackingField: 0
|
||||
<AssetPathHash>k__BackingField: 8652468816125699328
|
||||
SceneId: 0
|
||||
SerializedTransformProperties:
|
||||
Position: {x: -4.80351, y: 0.18147132, z: 5.430528}
|
||||
Rotation: {x: 0, y: 0, z: 0, w: 1}
|
||||
Scale: {x: 1, y: 1, z: 1}
|
||||
IsValid: 1
|
||||
--- !u!143 &4148834954576211901
|
||||
CharacterController:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 303449598114786579}
|
||||
m_Material: {fileID: 0}
|
||||
m_IsTrigger: 0
|
||||
m_Enabled: 1
|
||||
serializedVersion: 2
|
||||
m_Height: 2
|
||||
m_Radius: 0.5
|
||||
m_SlopeLimit: 45
|
||||
m_StepOffset: 0.3
|
||||
m_SkinWidth: 0.08
|
||||
m_MinMoveDistance: 0.001
|
||||
m_Center: {x: 0, y: 1, z: 0}
|
||||
--- !u!136 &8534672635240368605
|
||||
CapsuleCollider:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 303449598114786579}
|
||||
m_Material: {fileID: 0}
|
||||
m_IsTrigger: 0
|
||||
m_Enabled: 1
|
||||
m_Radius: 0.5
|
||||
m_Height: 2
|
||||
m_Direction: 1
|
||||
m_Center: {x: 0, y: 1, z: 0}
|
||||
--- !u!1 &2693313506199881053
|
||||
GameObject:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
serializedVersion: 6
|
||||
m_Component:
|
||||
- component: {fileID: 7416592246441027450}
|
||||
- component: {fileID: 1810266687591957409}
|
||||
- component: {fileID: 2367975056509727580}
|
||||
m_Layer: 4
|
||||
m_Name: SphereCollider
|
||||
m_TagString: Untagged
|
||||
m_Icon: {fileID: 0}
|
||||
m_NavMeshLayer: 0
|
||||
m_StaticEditorFlags: 0
|
||||
m_IsActive: 1
|
||||
--- !u!4 &7416592246441027450
|
||||
Transform:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 2693313506199881053}
|
||||
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: 303449598114786577}
|
||||
m_RootOrder: 1
|
||||
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
|
||||
--- !u!135 &1810266687591957409
|
||||
SphereCollider:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 2693313506199881053}
|
||||
m_Material: {fileID: 0}
|
||||
m_IsTrigger: 1
|
||||
m_Enabled: 1
|
||||
serializedVersion: 2
|
||||
m_Radius: 0.3
|
||||
m_Center: {x: 0, y: 0.26, z: 0}
|
||||
--- !u!114 &2367975056509727580
|
||||
MonoBehaviour:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 2693313506199881053}
|
||||
m_Enabled: 1
|
||||
m_EditorHideFlags: 0
|
||||
m_Script: {fileID: 11500000, guid: 3dc97a8b9e628044e83004c93095c14d, type: 3}
|
||||
m_Name:
|
||||
m_EditorClassIdentifier:
|
||||
_componentIndexCache: 2
|
||||
_addedNetworkObject: {fileID: 201277550}
|
||||
_networkObjectCache: {fileID: 201277550}
|
||||
MaximumSimultaneousHits: 16
|
||||
AdditionalSize: 0.1
|
||||
Layers:
|
||||
serializedVersion: 2
|
||||
m_Bits: 1
|
||||
--- !u!1 &5873068582516782542
|
||||
GameObject:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
serializedVersion: 6
|
||||
m_Component:
|
||||
- component: {fileID: 6952090537135875148}
|
||||
- component: {fileID: 6605329024375725182}
|
||||
- component: {fileID: 9006911641345807741}
|
||||
- component: {fileID: 8022627623488540705}
|
||||
m_Layer: 0
|
||||
m_Name: Capsule
|
||||
m_TagString: Untagged
|
||||
m_Icon: {fileID: 0}
|
||||
m_NavMeshLayer: 0
|
||||
m_StaticEditorFlags: 0
|
||||
m_IsActive: 1
|
||||
--- !u!4 &6952090537135875148
|
||||
Transform:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 5873068582516782542}
|
||||
m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
|
||||
m_LocalPosition: {x: 0, y: 1, z: 0}
|
||||
m_LocalScale: {x: 1, y: 1, z: 1}
|
||||
m_ConstrainProportionsScale: 0
|
||||
m_Children: []
|
||||
m_Father: {fileID: 303449598114786577}
|
||||
m_RootOrder: 0
|
||||
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
|
||||
--- !u!33 &6605329024375725182
|
||||
MeshFilter:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 5873068582516782542}
|
||||
m_Mesh: {fileID: 10208, guid: 0000000000000000e000000000000000, type: 0}
|
||||
--- !u!23 &9006911641345807741
|
||||
MeshRenderer:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 5873068582516782542}
|
||||
m_Enabled: 1
|
||||
m_CastShadows: 1
|
||||
m_ReceiveShadows: 1
|
||||
m_DynamicOccludee: 1
|
||||
m_StaticShadowCaster: 0
|
||||
m_MotionVectors: 1
|
||||
m_LightProbeUsage: 1
|
||||
m_ReflectionProbeUsage: 1
|
||||
m_RayTracingMode: 2
|
||||
m_RayTraceProcedural: 0
|
||||
m_RenderingLayerMask: 1
|
||||
m_RendererPriority: 0
|
||||
m_Materials:
|
||||
- {fileID: 10303, guid: 0000000000000000f000000000000000, type: 0}
|
||||
m_StaticBatchInfo:
|
||||
firstSubMesh: 0
|
||||
subMeshCount: 0
|
||||
m_StaticBatchRoot: {fileID: 0}
|
||||
m_ProbeAnchor: {fileID: 0}
|
||||
m_LightProbeVolumeOverride: {fileID: 0}
|
||||
m_ScaleInLightmap: 1
|
||||
m_ReceiveGI: 1
|
||||
m_PreserveUVs: 0
|
||||
m_IgnoreNormalsForChartDetection: 0
|
||||
m_ImportantGI: 0
|
||||
m_StitchLightmapSeams: 1
|
||||
m_SelectedEditorRenderState: 3
|
||||
m_MinimumChartSize: 4
|
||||
m_AutoUVMaxDistance: 0.5
|
||||
m_AutoUVMaxAngle: 89
|
||||
m_LightmapParameters: {fileID: 0}
|
||||
m_SortingLayerID: 0
|
||||
m_SortingLayer: 0
|
||||
m_SortingOrder: 0
|
||||
m_AdditionalVertexStreams: {fileID: 0}
|
||||
--- !u!114 &8022627623488540705
|
||||
MonoBehaviour:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 5873068582516782542}
|
||||
m_Enabled: 1
|
||||
m_EditorHideFlags: 0
|
||||
m_Script: {fileID: 11500000, guid: 453481867b26f7c43b5bf38802a5f50e, type: 3}
|
||||
m_Name:
|
||||
m_EditorClassIdentifier:
|
||||
_componentIndexCache: 1
|
||||
_addedNetworkObject: {fileID: 201277550}
|
||||
_networkObjectCache: {fileID: 201277550}
|
||||
_initializationSettings:
|
||||
TargetTransform: {fileID: 303449598114786577}
|
||||
DetachOnStart: 0
|
||||
AttachOnStop: 0
|
||||
_controllerMovementSettings:
|
||||
EnableTeleport: 0
|
||||
TeleportThreshold: 0
|
||||
AdaptiveInterpolationValue: 0
|
||||
InterpolationValue: 2
|
||||
SmoothedProperties: 4294967295
|
||||
SnapNonSmoothedProperties: 0
|
||||
_favorPredictionNetworkTransform: 1
|
||||
_spectatorMovementSettings:
|
||||
EnableTeleport: 0
|
||||
TeleportThreshold: 0
|
||||
AdaptiveInterpolationValue: 0
|
||||
InterpolationValue: 2
|
||||
SmoothedProperties: 4294967295
|
||||
SnapNonSmoothedProperties: 0
|
||||
+14
@@ -0,0 +1,14 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 5b712878ecece354ba4ffb026c0a221c
|
||||
PrefabImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
AssetOrigin:
|
||||
serializedVersion: 1
|
||||
productId: 207815
|
||||
packageName: 'FishNet: Networking Evolved'
|
||||
packageVersion: 4.6.22R
|
||||
assetPath: Assets/FishNet/Demos/Prediction/CharacterController/Prefabs/CharacterControllerPrediction.prefab
|
||||
uploadId: 866910
|
||||
@@ -0,0 +1,17 @@
|
||||
This demo shows how to use a character controller with our prediction system.
|
||||
|
||||
Important:
|
||||
* Beta ReplicateStates must be enabled to use this demo. You can toggle this setting using the Fish-Networking menu.
|
||||
|
||||
Setup:
|
||||
* Open demo scene.
|
||||
* Start server, host, or client only. You may test with parrelSync or host the project.
|
||||
|
||||
Notes:
|
||||
* Server and all clients run the same inputs. This is done by using State Forwarding on the NetworkObject inspector.
|
||||
* NetworkTrigger is used to attach to platforms. You may review code within the controller script to see attach logic and comments.
|
||||
On the prefab the trigger is attached as a child of the NetworkObject for sorting, but not under the graphical, as we do
|
||||
not want the trigger to be modified outside the tick system (graphical gets smoothed, and is updated outside the tick loop).
|
||||
* Moving platform predicts fully into the future so the client may step on it in real-time. See notes in MovingPlatform script.
|
||||
Spectated objects may appear to correct when moving onto the platform. This can be resolved by balancing the future
|
||||
prediction amount on the platform and the spectated objects.
|
||||
@@ -0,0 +1,14 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 242afb68b5bce2f40ab2da029c12d008
|
||||
TextScriptImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
AssetOrigin:
|
||||
serializedVersion: 1
|
||||
productId: 207815
|
||||
packageName: 'FishNet: Networking Evolved'
|
||||
packageVersion: 4.6.22R
|
||||
assetPath: Assets/FishNet/Demos/Prediction/CharacterController/ReadMe.txt
|
||||
uploadId: 866910
|
||||
@@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: eaf414b899169f04bb4b0d65424a40bf
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
+499
@@ -0,0 +1,499 @@
|
||||
using System;
|
||||
using FishNet.Component.Prediction;
|
||||
using FishNet.Connection;
|
||||
using FishNet.Object.Prediction;
|
||||
using FishNet.Transporting;
|
||||
using FishNet.Utility.Template;
|
||||
using UnityEngine;
|
||||
|
||||
namespace FishNet.Demo.Prediction.CharacterControllers
|
||||
{
|
||||
public class CharacterControllerPrediction : TickNetworkBehaviour
|
||||
{
|
||||
#region Types.
|
||||
/// <summary>
|
||||
/// One-time inputs accumulated over frames between ticks.
|
||||
/// </summary>
|
||||
public struct OneTimeInput
|
||||
{
|
||||
/// <summary>
|
||||
/// True to jump.
|
||||
/// </summary>
|
||||
public bool Jump;
|
||||
|
||||
/// <summary>
|
||||
/// Unset inputs.
|
||||
/// </summary>
|
||||
public void ResetState()
|
||||
{
|
||||
Jump = false;
|
||||
}
|
||||
}
|
||||
|
||||
public struct ReplicateData : IReplicateData
|
||||
{
|
||||
public ReplicateData(Vector2 input, bool run, OneTimeInput oneTimeInputs)
|
||||
{
|
||||
OneTimeInputs = oneTimeInputs;
|
||||
Input = input;
|
||||
Run = run;
|
||||
|
||||
_tick = 0;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// True if Jump input was pressed for the tick.
|
||||
/// </summary>
|
||||
public OneTimeInput OneTimeInputs;
|
||||
/// <summary>
|
||||
/// Current movement directions held.
|
||||
/// </summary>
|
||||
public Vector2 Input;
|
||||
/// <summary>
|
||||
/// True if run is held.
|
||||
/// </summary>
|
||||
public readonly bool Run;
|
||||
/// <summary>
|
||||
/// Tick is set at runtime. There is no need to manually assign this value.
|
||||
/// </summary>
|
||||
private uint _tick;
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
OneTimeInputs.ResetState();
|
||||
}
|
||||
|
||||
public uint GetTick() => _tick;
|
||||
public void SetTick(uint value) => _tick = value;
|
||||
}
|
||||
|
||||
public struct ReconcileData : IReconcileData
|
||||
{
|
||||
public ReconcileData(Vector3 position, float verticalVelocity, float stamina, MovingPlatform currentPlatform)
|
||||
{
|
||||
Position = position;
|
||||
VerticalVelocity = verticalVelocity;
|
||||
Stamina = stamina;
|
||||
CurrentPlatform = currentPlatform;
|
||||
|
||||
_tick = 0;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Position of the character.
|
||||
/// </summary>
|
||||
public Vector3 Position;
|
||||
/// <summary>
|
||||
/// Current vertical velocity.
|
||||
/// </summary>
|
||||
/// <remarks>Used to simulate jumps and falls.</remarks>
|
||||
public float VerticalVelocity;
|
||||
/// <summary>
|
||||
/// Amount of stamina remaining to run or jump.
|
||||
/// </summary>
|
||||
public float Stamina;
|
||||
public MovingPlatform CurrentPlatform;
|
||||
/// <summary>
|
||||
/// Tick is set at runtime. There is no need to manually assign this value.
|
||||
/// </summary>
|
||||
private uint _tick;
|
||||
public void Dispose() { }
|
||||
public uint GetTick() => _tick;
|
||||
public void SetTick(uint value) => _tick = value;
|
||||
}
|
||||
#endregion
|
||||
|
||||
/// <summary>
|
||||
/// Invokes whenever NetworkStart is called for owner.
|
||||
/// </summary>
|
||||
public static event Action<CharacterControllerPrediction> OnOwner;
|
||||
/// <summary>
|
||||
/// Current stamina remaining.
|
||||
/// </summary>
|
||||
public float Stamina { get; private set; }
|
||||
/// <summary>
|
||||
/// Amount of force for jumping.
|
||||
/// </summary>
|
||||
[Tooltip("Amount of force for jumping.")]
|
||||
[SerializeField]
|
||||
private float _jumpForce = 30f;
|
||||
/// <summary>
|
||||
/// How quickly to move.
|
||||
/// </summary>
|
||||
[Tooltip("How quickly to move.")]
|
||||
[SerializeField]
|
||||
private float _moveRate = 4f;
|
||||
/// <summary>
|
||||
/// Current vertical velocity.
|
||||
/// </summary>
|
||||
private float _verticalVelocity;
|
||||
/// <summary>
|
||||
/// One-time inputs accumulated over frames between ticks.
|
||||
/// </summary>
|
||||
private OneTimeInput _oneTimeInputs = new();
|
||||
/// <summary>
|
||||
/// Last data which was supplied during replicate outside of reconcile.
|
||||
/// </summary>
|
||||
private ReplicateData _lastTickedReplicateData = default;
|
||||
/// <summary>
|
||||
/// Current platform the player is on.
|
||||
/// </summary>
|
||||
private MovingPlatform _currentPlatform;
|
||||
/// <summary>
|
||||
/// Reference to the CharacterController component.
|
||||
/// </summary>
|
||||
private CharacterController _characterController;
|
||||
/// <summary>
|
||||
/// NetworkTrigger on this character; used to detact platforms.
|
||||
/// </summary>
|
||||
private NetworkTrigger _characterTrigger;
|
||||
/// <summary>
|
||||
/// maximum amount of stamina allowed.
|
||||
/// </summary>
|
||||
public const float Maximum_Stamina = 50f;
|
||||
|
||||
private void Awake()
|
||||
{
|
||||
_characterController = GetComponent<CharacterController>();
|
||||
|
||||
_characterTrigger = GetComponentInChildren<NetworkTrigger>();
|
||||
_characterTrigger.OnEnter += CharacterTrigger_OnEnter;
|
||||
_characterTrigger.OnExit += CharacterTrigger_OnExit;
|
||||
|
||||
SetTickCallbacks(TickCallback.Tick | TickCallback.PostTick);
|
||||
}
|
||||
|
||||
public override void OnOwnershipClient(NetworkConnection prevOwner)
|
||||
{
|
||||
if (IsOwner)
|
||||
OnOwner?.Invoke(this);
|
||||
}
|
||||
|
||||
private void Update()
|
||||
{
|
||||
SetOneTimeInputs();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Checks setting inputs which are one-time(not held).
|
||||
/// </summary>
|
||||
private void SetOneTimeInputs()
|
||||
{
|
||||
if (!IsOwner)
|
||||
return;
|
||||
|
||||
/* Check to jump. */
|
||||
if (Input.GetKeyDown(KeyCode.Space))
|
||||
_oneTimeInputs.Jump = true;
|
||||
}
|
||||
|
||||
protected override void TimeManager_OnTick()
|
||||
{
|
||||
PerformReplicate(BuildMoveData());
|
||||
}
|
||||
|
||||
protected override void TimeManager_OnPostTick()
|
||||
{
|
||||
/* Typically a CharacterController could send a reconcile within
|
||||
* OnTick, after completing all moving logic. However, this demo
|
||||
* uses a NetworkTrigger to jump on platforms, which we need the results
|
||||
* from before sending a reconcile. The NetworkTrigger/Collider components
|
||||
* trace after simulation which occurs between OnTick, and OnPostTick, therefor
|
||||
* the trace would have happened by the time OnPostTick is called. */
|
||||
CreateReconcile();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns replicate data to send as the controller.
|
||||
/// </summary>
|
||||
private ReplicateData BuildMoveData()
|
||||
{
|
||||
/* Only the controller needs to build move data.
|
||||
* This could be the server if the server if no owner, for example
|
||||
* such as AI, or the owner of the object. */
|
||||
if (!IsOwner)
|
||||
return default;
|
||||
|
||||
float horizontal = Input.GetAxisRaw("Horizontal");
|
||||
float vertical = Input.GetAxisRaw("Vertical");
|
||||
// Run when left shift is held.
|
||||
bool run = Input.GetKey(KeyCode.LeftShift);
|
||||
|
||||
ReplicateData md = new(new(horizontal, vertical), run, _oneTimeInputs);
|
||||
|
||||
// Reset one tine inputs since they've been processed for the tick.
|
||||
_oneTimeInputs.ResetState();
|
||||
|
||||
return md;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates a reconcile that is sent to clients.
|
||||
/// </summary>
|
||||
public override void CreateReconcile()
|
||||
{
|
||||
/* Both the server and client should create reconcile data.
|
||||
* The client will use their copy as a fallback if they do not
|
||||
* get data from the server, such as a dropped packet.
|
||||
*
|
||||
* The client will not reconcile unless it receives at least one
|
||||
* reconcile packet from the server for the tick. */
|
||||
|
||||
/* You do not have to reconcile every tick if you wish to
|
||||
* save bandwidth/perf, or simply feel as though it's not needed
|
||||
* for your game type.
|
||||
*
|
||||
* Even when not reconciling every tick it's still recommended
|
||||
* to build the reconcile as client; this cost is very little.*/
|
||||
|
||||
/* This is an example of only sending a reconcile occasionally
|
||||
* if the server. Simply uncomment the if statement below to
|
||||
* test this behavior. */
|
||||
// if (base.IsServerStarted)
|
||||
// {
|
||||
// // Exit early if 10 ticks have not passed.
|
||||
// if (base.TimeManager.LocalTick % 10 != 0) return;
|
||||
// }
|
||||
|
||||
// Build the data using current information and call the reconcile method.
|
||||
ReconcileData rd = new(transform.localPosition, _verticalVelocity, Stamina, _currentPlatform);
|
||||
PerformReconcile(rd);
|
||||
}
|
||||
|
||||
[Replicate]
|
||||
private void PerformReplicate(ReplicateData rd, ReplicateState state = ReplicateState.Invalid, Channel channel = Channel.Unreliable)
|
||||
{
|
||||
// Always use the tickDelta as your delta when performing actions inside replicate.
|
||||
float delta = (float)TimeManager.TickDelta;
|
||||
bool useDefaultForces = false;
|
||||
|
||||
/* When client only run some checks to
|
||||
* further predict the clients future movement.
|
||||
* This can keep the object more inlined with real-time by
|
||||
* guessing what the clients input might be before we
|
||||
* actually receive it.
|
||||
*
|
||||
* Doing this does risk a chance of graphical jitter in the
|
||||
* scenario a de-synchronization occurs, but if only predicting
|
||||
* a couple ticks the chances are low. */
|
||||
// See https://fish-networking.gitbook.io/docs/manual/guides/prediction/version-2/creating-code/predicting-states
|
||||
if (!IsServerStarted && !IsOwner)
|
||||
{
|
||||
/* If ticked then set last ticked value.
|
||||
* Ticked means the replicate is being run from the tick cycle, more
|
||||
* specifically NOT from a replay/reconcile. */
|
||||
if (state.ContainsTicked())
|
||||
{
|
||||
/* Dispose of old should it have anything that needs to be cleaned up.
|
||||
* If you are only using value types in your data you do not need to call Dispose.
|
||||
* You must implement dispose manually to cache any non-value types, if you wish. */
|
||||
_lastTickedReplicateData.Dispose();
|
||||
// Set new.
|
||||
_lastTickedReplicateData = rd;
|
||||
}
|
||||
/* In the future means there is no way the data can be known to this client
|
||||
* yet. For example, the client is running this script locally and due to
|
||||
* how networking works, they have not yet received the latest information from
|
||||
* the server.
|
||||
*
|
||||
* If in the future then we are only going to predict up to
|
||||
* a certain amount of ticks in the future. This is us assuming that the
|
||||
* server (or client which owns this in this case) is going to use the
|
||||
* same input for at least X number of ticks. You can predict none, or as many
|
||||
* as you like, but the more inputs you predict the higher likeliness of guessing
|
||||
* wrong. If you do however predict wrong often smoothing will cover up the mistake. */
|
||||
else if (state.IsFuture())
|
||||
{
|
||||
/* Predict up to 1 tick more. */
|
||||
if (rd.GetTick() - _lastTickedReplicateData.GetTick() > 1)
|
||||
{
|
||||
useDefaultForces = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* If here we are predicting the future. */
|
||||
|
||||
/* You likely do not need to dispose rd here since it would be default
|
||||
* when state is 'not created'. We are simply doing it for good practice, should your ReplicateData
|
||||
* contain any garbage collection. */
|
||||
rd.Dispose();
|
||||
|
||||
rd = _lastTickedReplicateData;
|
||||
|
||||
/* There are some fields you might not want to predict, for example
|
||||
* jump. The odds of a client pressing jump two ticks in a row is unlikely.
|
||||
* The stamina check below would likely prevent such a scenario.
|
||||
*
|
||||
* We're going to unset jump for this reason. */
|
||||
rd.OneTimeInputs.Jump = false;
|
||||
|
||||
/* Be aware that future predicting is not a one-size fits all
|
||||
* feature. How much you predict into the future, if at all, depends
|
||||
* on your game mechanics and your desired outcome. */
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Vector3 forces;
|
||||
|
||||
if (useDefaultForces)
|
||||
{
|
||||
/* Character controllers are a bit problematic with colliders.
|
||||
* If you were to pass Vector3.zero into the move then there's
|
||||
* a chance other colliders will clip through the characterController.
|
||||
* When this is combined with reconciles, it's practically gauranteed
|
||||
* this will happen.
|
||||
*
|
||||
* Because of this issue, if we are 'using default forces' we will apply a
|
||||
* very insignificant amount of force which makes the characterController
|
||||
* update properly. */
|
||||
forces = new(0f, -1f, 0f);
|
||||
}
|
||||
// Calculate forces.
|
||||
else
|
||||
{
|
||||
// Stamina regained over every second.
|
||||
const float regainedStamina = 25f;
|
||||
// Add stamina with every tick.
|
||||
ModifyStamina(regainedStamina * delta);
|
||||
|
||||
// Add gravity. Extra gravity is added for snappier jumps.
|
||||
_verticalVelocity += Physics.gravity.y * delta * 3f;
|
||||
//Cap gravity to -20f so the player doesn't fall too fast.
|
||||
if (_verticalVelocity < -40f)
|
||||
_verticalVelocity = -40f;
|
||||
|
||||
//Normalize direction so the player does not move faster at angles.
|
||||
rd.Input = rd.Input.normalized;
|
||||
|
||||
/* Typically speaking any modification which can affect your CSP (prediction) should occur
|
||||
* inside replicate. This is why we add/remove stamina, and move within replicate. */
|
||||
|
||||
//Default run multiplier.
|
||||
float runMultiplier;
|
||||
//Stamina required to run over a second.
|
||||
const float runStamina = 50f;
|
||||
if (rd.Run && TryRemoveStamina(runStamina * delta))
|
||||
runMultiplier = 1.5f;
|
||||
else
|
||||
runMultiplier = 1f;
|
||||
|
||||
//Stamina required to jump.
|
||||
const byte jumpStamina = 30;
|
||||
/* For consistent jumps set to jump force when jumping, rather
|
||||
* than add force onto current gravity. */
|
||||
if (rd.OneTimeInputs.Jump && TryRemoveStamina(jumpStamina))
|
||||
_verticalVelocity = _jumpForce;
|
||||
|
||||
forces = new Vector3(rd.Input.x, 0f, rd.Input.y) * (_moveRate * runMultiplier);
|
||||
//Add vertical velocity to forces.
|
||||
forces.y = _verticalVelocity;
|
||||
}
|
||||
|
||||
_characterController.Move(forces * delta);
|
||||
}
|
||||
|
||||
[Reconcile]
|
||||
private void PerformReconcile(ReconcileData rd, Channel channel = Channel.Unreliable)
|
||||
{
|
||||
/* Simply set current values to as they are
|
||||
* in the reconcile data. */
|
||||
_verticalVelocity = rd.VerticalVelocity;
|
||||
Stamina = rd.Stamina;
|
||||
|
||||
/* It is VERY important to disable the CharacterController
|
||||
* component before updating its position. If you do not
|
||||
* use the disable/enable work-around below, the Transform
|
||||
* will show the correct position but the physics for
|
||||
* the CharacterController will remain at it's prior position
|
||||
* until the next simulate. */
|
||||
_characterController.enabled = false;
|
||||
|
||||
/* Even though the platform is traced for in replicate we must also
|
||||
* pass the current platform into the reconcile, and set our local value
|
||||
* to whatever is provided in the reconcile.
|
||||
*
|
||||
* This is done because we use local position to reset the character
|
||||
* and if the clients currentPlatform differs from what the server
|
||||
* had when reconciling the world position would be significantly
|
||||
* different due to the parent not aligning. */
|
||||
_currentPlatform = rd.CurrentPlatform;
|
||||
//Set transform parent after assigning current.
|
||||
SetParent();
|
||||
/* Update position AFTER setting the parent, otherwise
|
||||
* you would face a potentially huge positional de-sync
|
||||
* as mentioned above. */
|
||||
transform.localPosition = rd.Position;
|
||||
|
||||
_characterController.enabled = true;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Called when the trigger on this object enters another collider.
|
||||
/// </summary>
|
||||
private void CharacterTrigger_OnEnter(Collider c)
|
||||
{
|
||||
//We only care about moving platforms.
|
||||
if (!c.TryGetComponent(out MovingPlatform mp))
|
||||
return;
|
||||
|
||||
_currentPlatform = mp;
|
||||
SetParent();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Called when the trigger on this object exits another collider.
|
||||
/// </summary>
|
||||
private void CharacterTrigger_OnExit(Collider c)
|
||||
{
|
||||
if (c == null)
|
||||
return;
|
||||
if (!c.TryGetComponent(out MovingPlatform mp))
|
||||
return;
|
||||
|
||||
//Only check if already attached to a platform.
|
||||
if (_currentPlatform == null)
|
||||
return;
|
||||
//Not the current platform.
|
||||
if (_currentPlatform != mp)
|
||||
return;
|
||||
|
||||
//Is the current platform, unset.
|
||||
_currentPlatform = null;
|
||||
SetParent();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Updates parent state based on current platforms value.
|
||||
/// </summary>
|
||||
private void SetParent()
|
||||
{
|
||||
if (_currentPlatform != null)
|
||||
transform.SetParent(_currentPlatform.transform);
|
||||
else
|
||||
transform.SetParent(null);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Modifies stamina by adding or removing stamina.
|
||||
/// </summary>
|
||||
private void ModifyStamina(float value)
|
||||
{
|
||||
float next = Stamina + value;
|
||||
Stamina = Mathf.Clamp(next, 0f, Maximum_Stamina);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Removes stamina if enough stamina is available.
|
||||
/// </summary>
|
||||
/// <returns>>True if stamina was available and removed.</returns>
|
||||
private bool TryRemoveStamina(float value)
|
||||
{
|
||||
if (Stamina < value)
|
||||
return false;
|
||||
|
||||
Stamina -= value;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
+18
@@ -0,0 +1,18 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 53a6d84aa5d214e48a7308646e5d20da
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
AssetOrigin:
|
||||
serializedVersion: 1
|
||||
productId: 207815
|
||||
packageName: 'FishNet: Networking Evolved'
|
||||
packageVersion: 4.6.22R
|
||||
assetPath: Assets/FishNet/Demos/Prediction/CharacterController/Scripts/CharacterControllerPrediction.cs
|
||||
uploadId: 866910
|
||||
@@ -0,0 +1,144 @@
|
||||
using System.Collections.Generic;
|
||||
using FishNet.Object;
|
||||
using FishNet.Object.Prediction;
|
||||
using FishNet.Transporting;
|
||||
using FishNet.Utility.Template;
|
||||
using UnityEngine;
|
||||
|
||||
namespace FishNet.Demo.Prediction.CharacterControllers
|
||||
{
|
||||
public class MovingPlatform : TickNetworkBehaviour
|
||||
{
|
||||
#region Types.
|
||||
public struct ReplicateData : IReplicateData
|
||||
{
|
||||
public ReplicateData(uint unused = 0)
|
||||
{
|
||||
_tick = 0;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Tick is set at runtime. There is no need to manually assign this value.
|
||||
/// </summary>
|
||||
private uint _tick;
|
||||
public void Dispose() { }
|
||||
public uint GetTick() => _tick;
|
||||
public void SetTick(uint value) => _tick = value;
|
||||
}
|
||||
|
||||
public struct ReconcileData : IReconcileData
|
||||
{
|
||||
public ReconcileData(Vector3 position, byte goalIndex)
|
||||
{
|
||||
Position = position;
|
||||
GoalIndex = goalIndex;
|
||||
_tick = 0;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Position of the character.
|
||||
/// </summary>
|
||||
public Vector3 Position;
|
||||
/// <summary>
|
||||
/// Current vertical velocity.
|
||||
/// </summary>
|
||||
/// <remarks>Used to simulate jumps and falls.</remarks>
|
||||
public byte GoalIndex;
|
||||
/// <summary>
|
||||
/// Tick is set at runtime. There is no need to manually assign this value.
|
||||
/// </summary>
|
||||
private uint _tick;
|
||||
public void Dispose() { }
|
||||
public uint GetTick() => _tick;
|
||||
public void SetTick(uint value) => _tick = value;
|
||||
}
|
||||
#endregion
|
||||
|
||||
[SerializeField]
|
||||
private float _moveRate = 4f;
|
||||
/// <summary>
|
||||
/// Goal to move towards.
|
||||
/// </summary>
|
||||
private byte _goalIndex;
|
||||
/// <summary>
|
||||
/// Goals to move towards.
|
||||
/// </summary>
|
||||
private List<Vector3> _goals = new();
|
||||
|
||||
private void Awake()
|
||||
{
|
||||
const float offset = 5f;
|
||||
Vector3 position = transform.position;
|
||||
_goals.Add(position + new Vector3(0f, 0f, offset));
|
||||
_goals.Add(position + new Vector3(0f, 0f, -offset));
|
||||
}
|
||||
|
||||
public override void OnStartNetwork()
|
||||
{
|
||||
SetTickCallbacks(TickCallback.Tick);
|
||||
}
|
||||
|
||||
protected override void TimeManager_OnTick()
|
||||
{
|
||||
PerformReplicate(default);
|
||||
CreateReconcile();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates a reconcile that is sent to clients.
|
||||
/// </summary>
|
||||
public override void CreateReconcile()
|
||||
{
|
||||
ReconcileData rd = new(transform.position, _goalIndex);
|
||||
PerformReconcile(rd);
|
||||
}
|
||||
|
||||
[Replicate]
|
||||
private void PerformReplicate(ReplicateData rd, ReplicateState state = ReplicateState.Invalid, Channel channel = Channel.Unreliable)
|
||||
{
|
||||
/* Move logic is always called regardless of state.
|
||||
*
|
||||
* This means that move will be called when replaying after a reconcile,
|
||||
* as well during OnTick, as well even if there is no data being received
|
||||
* from the server (IsFuture).
|
||||
*
|
||||
* By doing this we allow the platform to be ahead of what the client has
|
||||
* received by the server.
|
||||
*
|
||||
* When observed the client will actually see the platform
|
||||
* ahead of the server depending on their ping, being more ahead with higher pings.
|
||||
* This is the desired outcome as that's where the platform will be by the time
|
||||
* the client sends input to the server. If the platform was not ahead of the server
|
||||
* then when the client perhaps jumped onto it, the platform would actually be further
|
||||
* on the server then where the client observed it. In result, the client would snap to
|
||||
* a correct position when landing on the platform.
|
||||
*
|
||||
* If you want to visually see this simple uncomment the line below. Be sure to add
|
||||
* latency to make the correction more noticeable. */
|
||||
// if (state.IsFuture())
|
||||
// return;
|
||||
|
||||
// Always use the tickDelta as your delta when performing actions inside replicate.
|
||||
float delta = (float)TimeManager.TickDelta;
|
||||
|
||||
Vector3 goal = _goals[_goalIndex];
|
||||
Vector3 next = Vector3.MoveTowards(transform.position, goal, delta * _moveRate);
|
||||
|
||||
transform.position = next;
|
||||
|
||||
if (next == goal)
|
||||
{
|
||||
_goalIndex++;
|
||||
if (_goalIndex >= _goals.Count)
|
||||
_goalIndex = 0;
|
||||
}
|
||||
}
|
||||
|
||||
[Reconcile]
|
||||
private void PerformReconcile(ReconcileData rd, Channel channel = Channel.Unreliable)
|
||||
{
|
||||
transform.position = rd.Position;
|
||||
_goalIndex = rd.GoalIndex;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 0fca32023f23445429675b0c692d00d1
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
AssetOrigin:
|
||||
serializedVersion: 1
|
||||
productId: 207815
|
||||
packageName: 'FishNet: Networking Evolved'
|
||||
packageVersion: 4.6.22R
|
||||
assetPath: Assets/FishNet/Demos/Prediction/CharacterController/Scripts/MovingPlatform.cs
|
||||
uploadId: 866910
|
||||
@@ -0,0 +1 @@
|
||||
//Intentionally left blank.
|
||||
@@ -0,0 +1,18 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 2ca42d40476d05444acd0179c78b44cc
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
AssetOrigin:
|
||||
serializedVersion: 1
|
||||
productId: 207815
|
||||
packageName: 'FishNet: Networking Evolved'
|
||||
packageVersion: 4.6.22R
|
||||
assetPath: Assets/FishNet/Demos/Prediction/CharacterController/Scripts/StaminaCanvas.cs
|
||||
uploadId: 866910
|
||||
@@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: d3aa9f1d4a89e9d438bd7a3048417f2f
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
BIN
Binary file not shown.
+154
@@ -0,0 +1,154 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 26148ffb3c1a62d4cb3446654373058b
|
||||
TextureImporter:
|
||||
internalIDToNameTable: []
|
||||
externalObjects: {}
|
||||
serializedVersion: 12
|
||||
mipmaps:
|
||||
mipMapMode: 0
|
||||
enableMipMap: 0
|
||||
sRGBTexture: 1
|
||||
linearTexture: 0
|
||||
fadeOut: 0
|
||||
borderMipMap: 0
|
||||
mipMapsPreserveCoverage: 0
|
||||
alphaTestReferenceValue: 0.5
|
||||
mipMapFadeDistanceStart: 1
|
||||
mipMapFadeDistanceEnd: 3
|
||||
bumpmap:
|
||||
convertToNormalMap: 0
|
||||
externalNormalMap: 0
|
||||
heightScale: 0.25
|
||||
normalMapFilter: 0
|
||||
isReadable: 0
|
||||
streamingMipmaps: 0
|
||||
streamingMipmapsPriority: 0
|
||||
vTOnly: 0
|
||||
ignoreMasterTextureLimit: 0
|
||||
grayScaleToAlpha: 0
|
||||
generateCubemap: 6
|
||||
cubemapConvolution: 0
|
||||
seamlessCubemap: 0
|
||||
textureFormat: 1
|
||||
maxTextureSize: 2048
|
||||
textureSettings:
|
||||
serializedVersion: 2
|
||||
filterMode: 1
|
||||
aniso: 1
|
||||
mipBias: 0
|
||||
wrapU: 1
|
||||
wrapV: 1
|
||||
wrapW: 0
|
||||
nPOTScale: 0
|
||||
lightmap: 0
|
||||
compressionQuality: 50
|
||||
spriteMode: 1
|
||||
spriteExtrude: 1
|
||||
spriteMeshType: 1
|
||||
alignment: 0
|
||||
spritePivot: {x: 0.5, y: 0.5}
|
||||
spritePixelsToUnits: 100
|
||||
spriteBorder: {x: 0, y: 0, z: 0, w: 0}
|
||||
spriteGenerateFallbackPhysicsShape: 1
|
||||
alphaUsage: 1
|
||||
alphaIsTransparency: 1
|
||||
spriteTessellationDetail: -1
|
||||
textureType: 8
|
||||
textureShape: 1
|
||||
singleChannelComponent: 0
|
||||
flipbookRows: 1
|
||||
flipbookColumns: 1
|
||||
maxTextureSizeSet: 0
|
||||
compressionQualitySet: 0
|
||||
textureFormatSet: 0
|
||||
ignorePngGamma: 0
|
||||
applyGammaDecoding: 0
|
||||
cookieLightType: 0
|
||||
platformSettings:
|
||||
- serializedVersion: 3
|
||||
buildTarget: DefaultTexturePlatform
|
||||
maxTextureSize: 512
|
||||
resizeAlgorithm: 0
|
||||
textureFormat: -1
|
||||
textureCompression: 1
|
||||
compressionQuality: 50
|
||||
crunchedCompression: 0
|
||||
allowsAlphaSplitting: 0
|
||||
overridden: 0
|
||||
androidETC2FallbackOverride: 0
|
||||
forceMaximumCompressionQuality_BC6H_BC7: 0
|
||||
- serializedVersion: 3
|
||||
buildTarget: Standalone
|
||||
maxTextureSize: 2048
|
||||
resizeAlgorithm: 0
|
||||
textureFormat: -1
|
||||
textureCompression: 1
|
||||
compressionQuality: 50
|
||||
crunchedCompression: 0
|
||||
allowsAlphaSplitting: 0
|
||||
overridden: 0
|
||||
androidETC2FallbackOverride: 0
|
||||
forceMaximumCompressionQuality_BC6H_BC7: 0
|
||||
- serializedVersion: 3
|
||||
buildTarget: iPhone
|
||||
maxTextureSize: 2048
|
||||
resizeAlgorithm: 0
|
||||
textureFormat: -1
|
||||
textureCompression: 1
|
||||
compressionQuality: 50
|
||||
crunchedCompression: 0
|
||||
allowsAlphaSplitting: 0
|
||||
overridden: 0
|
||||
androidETC2FallbackOverride: 0
|
||||
forceMaximumCompressionQuality_BC6H_BC7: 0
|
||||
- serializedVersion: 3
|
||||
buildTarget: WebGL
|
||||
maxTextureSize: 2048
|
||||
resizeAlgorithm: 0
|
||||
textureFormat: -1
|
||||
textureCompression: 1
|
||||
compressionQuality: 50
|
||||
crunchedCompression: 0
|
||||
allowsAlphaSplitting: 0
|
||||
overridden: 0
|
||||
androidETC2FallbackOverride: 0
|
||||
forceMaximumCompressionQuality_BC6H_BC7: 0
|
||||
- serializedVersion: 3
|
||||
buildTarget: Android
|
||||
maxTextureSize: 2048
|
||||
resizeAlgorithm: 0
|
||||
textureFormat: -1
|
||||
textureCompression: 1
|
||||
compressionQuality: 50
|
||||
crunchedCompression: 0
|
||||
allowsAlphaSplitting: 0
|
||||
overridden: 0
|
||||
androidETC2FallbackOverride: 0
|
||||
forceMaximumCompressionQuality_BC6H_BC7: 0
|
||||
spriteSheet:
|
||||
serializedVersion: 2
|
||||
sprites: []
|
||||
outline: []
|
||||
physicsShape: []
|
||||
bones: []
|
||||
spriteID: 5e97eb03825dee720800000000000000
|
||||
internalID: 0
|
||||
vertices: []
|
||||
indices:
|
||||
edges: []
|
||||
weights: []
|
||||
secondaryTextures: []
|
||||
nameFileIdTable: {}
|
||||
spritePackingTag:
|
||||
pSDRemoveMatte: 0
|
||||
pSDShowRemoveMatteOption: 0
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
AssetOrigin:
|
||||
serializedVersion: 1
|
||||
productId: 207815
|
||||
packageName: 'FishNet: Networking Evolved'
|
||||
packageVersion: 4.6.22R
|
||||
assetPath: Assets/FishNet/Demos/Prediction/CharacterController/Textures/AdaptiveInterpolation_Img.png
|
||||
uploadId: 866910
|
||||
BIN
Binary file not shown.
+154
@@ -0,0 +1,154 @@
|
||||
fileFormatVersion: 2
|
||||
guid: e93a25d03197614429e1a8b5600d5a97
|
||||
TextureImporter:
|
||||
internalIDToNameTable: []
|
||||
externalObjects: {}
|
||||
serializedVersion: 12
|
||||
mipmaps:
|
||||
mipMapMode: 0
|
||||
enableMipMap: 0
|
||||
sRGBTexture: 1
|
||||
linearTexture: 0
|
||||
fadeOut: 0
|
||||
borderMipMap: 0
|
||||
mipMapsPreserveCoverage: 0
|
||||
alphaTestReferenceValue: 0.5
|
||||
mipMapFadeDistanceStart: 1
|
||||
mipMapFadeDistanceEnd: 3
|
||||
bumpmap:
|
||||
convertToNormalMap: 0
|
||||
externalNormalMap: 0
|
||||
heightScale: 0.25
|
||||
normalMapFilter: 0
|
||||
isReadable: 0
|
||||
streamingMipmaps: 0
|
||||
streamingMipmapsPriority: 0
|
||||
vTOnly: 0
|
||||
ignoreMasterTextureLimit: 0
|
||||
grayScaleToAlpha: 0
|
||||
generateCubemap: 6
|
||||
cubemapConvolution: 0
|
||||
seamlessCubemap: 0
|
||||
textureFormat: 1
|
||||
maxTextureSize: 2048
|
||||
textureSettings:
|
||||
serializedVersion: 2
|
||||
filterMode: 1
|
||||
aniso: 1
|
||||
mipBias: 0
|
||||
wrapU: 1
|
||||
wrapV: 1
|
||||
wrapW: 0
|
||||
nPOTScale: 0
|
||||
lightmap: 0
|
||||
compressionQuality: 50
|
||||
spriteMode: 1
|
||||
spriteExtrude: 1
|
||||
spriteMeshType: 1
|
||||
alignment: 0
|
||||
spritePivot: {x: 0.5, y: 0.5}
|
||||
spritePixelsToUnits: 100
|
||||
spriteBorder: {x: 0, y: 0, z: 0, w: 0}
|
||||
spriteGenerateFallbackPhysicsShape: 1
|
||||
alphaUsage: 1
|
||||
alphaIsTransparency: 1
|
||||
spriteTessellationDetail: -1
|
||||
textureType: 8
|
||||
textureShape: 1
|
||||
singleChannelComponent: 0
|
||||
flipbookRows: 1
|
||||
flipbookColumns: 1
|
||||
maxTextureSizeSet: 0
|
||||
compressionQualitySet: 0
|
||||
textureFormatSet: 0
|
||||
ignorePngGamma: 0
|
||||
applyGammaDecoding: 0
|
||||
cookieLightType: 0
|
||||
platformSettings:
|
||||
- serializedVersion: 3
|
||||
buildTarget: DefaultTexturePlatform
|
||||
maxTextureSize: 512
|
||||
resizeAlgorithm: 0
|
||||
textureFormat: -1
|
||||
textureCompression: 1
|
||||
compressionQuality: 50
|
||||
crunchedCompression: 0
|
||||
allowsAlphaSplitting: 0
|
||||
overridden: 0
|
||||
androidETC2FallbackOverride: 0
|
||||
forceMaximumCompressionQuality_BC6H_BC7: 0
|
||||
- serializedVersion: 3
|
||||
buildTarget: Standalone
|
||||
maxTextureSize: 2048
|
||||
resizeAlgorithm: 0
|
||||
textureFormat: -1
|
||||
textureCompression: 1
|
||||
compressionQuality: 50
|
||||
crunchedCompression: 0
|
||||
allowsAlphaSplitting: 0
|
||||
overridden: 0
|
||||
androidETC2FallbackOverride: 0
|
||||
forceMaximumCompressionQuality_BC6H_BC7: 0
|
||||
- serializedVersion: 3
|
||||
buildTarget: iPhone
|
||||
maxTextureSize: 2048
|
||||
resizeAlgorithm: 0
|
||||
textureFormat: -1
|
||||
textureCompression: 1
|
||||
compressionQuality: 50
|
||||
crunchedCompression: 0
|
||||
allowsAlphaSplitting: 0
|
||||
overridden: 0
|
||||
androidETC2FallbackOverride: 0
|
||||
forceMaximumCompressionQuality_BC6H_BC7: 0
|
||||
- serializedVersion: 3
|
||||
buildTarget: WebGL
|
||||
maxTextureSize: 2048
|
||||
resizeAlgorithm: 0
|
||||
textureFormat: -1
|
||||
textureCompression: 1
|
||||
compressionQuality: 50
|
||||
crunchedCompression: 0
|
||||
allowsAlphaSplitting: 0
|
||||
overridden: 0
|
||||
androidETC2FallbackOverride: 0
|
||||
forceMaximumCompressionQuality_BC6H_BC7: 0
|
||||
- serializedVersion: 3
|
||||
buildTarget: Android
|
||||
maxTextureSize: 2048
|
||||
resizeAlgorithm: 0
|
||||
textureFormat: -1
|
||||
textureCompression: 1
|
||||
compressionQuality: 50
|
||||
crunchedCompression: 0
|
||||
allowsAlphaSplitting: 0
|
||||
overridden: 0
|
||||
androidETC2FallbackOverride: 0
|
||||
forceMaximumCompressionQuality_BC6H_BC7: 0
|
||||
spriteSheet:
|
||||
serializedVersion: 2
|
||||
sprites: []
|
||||
outline: []
|
||||
physicsShape: []
|
||||
bones: []
|
||||
spriteID: 5e97eb03825dee720800000000000000
|
||||
internalID: 0
|
||||
vertices: []
|
||||
indices:
|
||||
edges: []
|
||||
weights: []
|
||||
secondaryTextures: []
|
||||
nameFileIdTable: {}
|
||||
spritePackingTag:
|
||||
pSDRemoveMatte: 0
|
||||
pSDShowRemoveMatteOption: 0
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
AssetOrigin:
|
||||
serializedVersion: 1
|
||||
productId: 207815
|
||||
packageName: 'FishNet: Networking Evolved'
|
||||
packageVersion: 4.6.22R
|
||||
assetPath: Assets/FishNet/Demos/Prediction/CharacterController/Textures/FlatInterpolation_Img.png
|
||||
uploadId: 866910
|
||||
Binary file not shown.
@@ -0,0 +1,111 @@
|
||||
fileFormatVersion: 2
|
||||
guid: f9b2bae1e919cc648a88e211cd094c53
|
||||
TextureImporter:
|
||||
internalIDToNameTable: []
|
||||
externalObjects: {}
|
||||
serializedVersion: 11
|
||||
mipmaps:
|
||||
mipMapMode: 0
|
||||
enableMipMap: 0
|
||||
sRGBTexture: 1
|
||||
linearTexture: 0
|
||||
fadeOut: 0
|
||||
borderMipMap: 0
|
||||
mipMapsPreserveCoverage: 0
|
||||
alphaTestReferenceValue: 0.5
|
||||
mipMapFadeDistanceStart: 1
|
||||
mipMapFadeDistanceEnd: 3
|
||||
bumpmap:
|
||||
convertToNormalMap: 0
|
||||
externalNormalMap: 0
|
||||
heightScale: 0.25
|
||||
normalMapFilter: 0
|
||||
isReadable: 0
|
||||
streamingMipmaps: 0
|
||||
streamingMipmapsPriority: 0
|
||||
grayScaleToAlpha: 0
|
||||
generateCubemap: 6
|
||||
cubemapConvolution: 0
|
||||
seamlessCubemap: 0
|
||||
textureFormat: 1
|
||||
maxTextureSize: 2048
|
||||
textureSettings:
|
||||
serializedVersion: 2
|
||||
filterMode: 1
|
||||
aniso: 1
|
||||
mipBias: 0
|
||||
wrapU: 1
|
||||
wrapV: 1
|
||||
wrapW: 0
|
||||
nPOTScale: 0
|
||||
lightmap: 0
|
||||
compressionQuality: 50
|
||||
spriteMode: 1
|
||||
spriteExtrude: 1
|
||||
spriteMeshType: 1
|
||||
alignment: 0
|
||||
spritePivot: {x: 0.5, y: 0.5}
|
||||
spritePixelsToUnits: 1
|
||||
spriteBorder: {x: 0, y: 0, z: 0, w: 0}
|
||||
spriteGenerateFallbackPhysicsShape: 1
|
||||
alphaUsage: 1
|
||||
alphaIsTransparency: 1
|
||||
spriteTessellationDetail: -1
|
||||
textureType: 8
|
||||
textureShape: 1
|
||||
singleChannelComponent: 0
|
||||
maxTextureSizeSet: 0
|
||||
compressionQualitySet: 0
|
||||
textureFormatSet: 0
|
||||
applyGammaDecoding: 0
|
||||
platformSettings:
|
||||
- serializedVersion: 3
|
||||
buildTarget: DefaultTexturePlatform
|
||||
maxTextureSize: 2048
|
||||
resizeAlgorithm: 0
|
||||
textureFormat: -1
|
||||
textureCompression: 1
|
||||
compressionQuality: 50
|
||||
crunchedCompression: 0
|
||||
allowsAlphaSplitting: 0
|
||||
overridden: 0
|
||||
androidETC2FallbackOverride: 0
|
||||
forceMaximumCompressionQuality_BC6H_BC7: 0
|
||||
- serializedVersion: 3
|
||||
buildTarget: Standalone
|
||||
maxTextureSize: 2048
|
||||
resizeAlgorithm: 0
|
||||
textureFormat: -1
|
||||
textureCompression: 1
|
||||
compressionQuality: 50
|
||||
crunchedCompression: 0
|
||||
allowsAlphaSplitting: 0
|
||||
overridden: 0
|
||||
androidETC2FallbackOverride: 0
|
||||
forceMaximumCompressionQuality_BC6H_BC7: 0
|
||||
spriteSheet:
|
||||
serializedVersion: 2
|
||||
sprites: []
|
||||
outline: []
|
||||
physicsShape: []
|
||||
bones: []
|
||||
spriteID: 5e97eb03825dee720800000000000000
|
||||
internalID: 0
|
||||
vertices: []
|
||||
indices:
|
||||
edges: []
|
||||
weights: []
|
||||
secondaryTextures: []
|
||||
spritePackingTag:
|
||||
pSDRemoveMatte: 0
|
||||
pSDShowRemoveMatteOption: 0
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
AssetOrigin:
|
||||
serializedVersion: 1
|
||||
productId: 207815
|
||||
packageName: 'FishNet: Networking Evolved'
|
||||
packageVersion: 4.6.22R
|
||||
assetPath: Assets/FishNet/Demos/Prediction/CharacterController/Textures/Stamina_Bar.png
|
||||
uploadId: 866910
|
||||
Reference in New Issue
Block a user