[Add] FishNet

This commit is contained in:
2026-03-30 20:11:57 +07:00
parent ee793a3361
commit c22c08753a
1797 changed files with 197950 additions and 1 deletions
@@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: accc5b93ebf3b0040baaec2298c7d394
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:
@@ -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:
@@ -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
@@ -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:
@@ -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;
}
}
}
@@ -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:
@@ -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
@@ -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
@@ -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
@@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 6f3426c410532ce438e1d80868d45500
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:
@@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 15ebc39fcc93fdf478b190c392816c1e
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:
@@ -0,0 +1,77 @@
%YAML 1.1
%TAG !u! tag:unity3d.com,2011:
--- !u!21 &2100000
Material:
serializedVersion: 6
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_Name: BlueMat
m_Shader: {fileID: 46, guid: 0000000000000000f000000000000000, type: 0}
m_ShaderKeywords:
m_LightmapFlags: 4
m_EnableInstancingVariants: 0
m_DoubleSidedGI: 0
m_CustomRenderQueue: -1
stringTagMap: {}
disabledShaderPasses: []
m_SavedProperties:
serializedVersion: 3
m_TexEnvs:
- _BumpMap:
m_Texture: {fileID: 0}
m_Scale: {x: 1, y: 1}
m_Offset: {x: 0, y: 0}
- _DetailAlbedoMap:
m_Texture: {fileID: 0}
m_Scale: {x: 1, y: 1}
m_Offset: {x: 0, y: 0}
- _DetailMask:
m_Texture: {fileID: 0}
m_Scale: {x: 1, y: 1}
m_Offset: {x: 0, y: 0}
- _DetailNormalMap:
m_Texture: {fileID: 0}
m_Scale: {x: 1, y: 1}
m_Offset: {x: 0, y: 0}
- _EmissionMap:
m_Texture: {fileID: 0}
m_Scale: {x: 1, y: 1}
m_Offset: {x: 0, y: 0}
- _MainTex:
m_Texture: {fileID: 0}
m_Scale: {x: 1, y: 1}
m_Offset: {x: 0, y: 0}
- _MetallicGlossMap:
m_Texture: {fileID: 0}
m_Scale: {x: 1, y: 1}
m_Offset: {x: 0, y: 0}
- _OcclusionMap:
m_Texture: {fileID: 0}
m_Scale: {x: 1, y: 1}
m_Offset: {x: 0, y: 0}
- _ParallaxMap:
m_Texture: {fileID: 0}
m_Scale: {x: 1, y: 1}
m_Offset: {x: 0, y: 0}
m_Floats:
- _BumpScale: 1
- _Cutoff: 0.5
- _DetailNormalMapScale: 1
- _DstBlend: 0
- _GlossMapScale: 1
- _Glossiness: 0.5
- _GlossyReflections: 1
- _Metallic: 0
- _Mode: 0
- _OcclusionStrength: 1
- _Parallax: 0.02
- _SmoothnessTextureChannel: 0
- _SpecularHighlights: 1
- _SrcBlend: 1
- _UVSec: 0
- _ZWrite: 1
m_Colors:
- _Color: {r: 0, g: 0.363446, b: 0.5471698, a: 1}
- _EmissionColor: {r: 0, g: 0, b: 0, a: 1}
@@ -0,0 +1,15 @@
fileFormatVersion: 2
guid: 67717b2583b1d8644a7ed4857736c9cd
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/Rigidbody/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: FrontWheel
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.71853435, g: 0.5330188, b: 1, a: 1}
- _EmissionColor: {r: 0, g: 0, b: 0, a: 1}
m_BuildTextureStacks: []
@@ -0,0 +1,15 @@
fileFormatVersion: 2
guid: c9adb005e24322147b85e0d1ed5fa70e
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/Rigidbody/Materials/FrontWheel.mat
uploadId: 866910
@@ -0,0 +1,82 @@
%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: GreenMat
m_Shader: {fileID: 46, guid: 0000000000000000f000000000000000, type: 0}
m_ValidKeywords:
- _ALPHAPREMULTIPLY_ON
m_InvalidKeywords: []
m_LightmapFlags: 4
m_EnableInstancingVariants: 0
m_DoubleSidedGI: 0
m_CustomRenderQueue: 3000
stringTagMap:
RenderType: Transparent
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: 10
- _GlossMapScale: 1
- _Glossiness: 0.5
- _GlossyReflections: 1
- _Metallic: 0
- _Mode: 3
- _OcclusionStrength: 1
- _Parallax: 0.02
- _SmoothnessTextureChannel: 0
- _SpecularHighlights: 1
- _SrcBlend: 1
- _UVSec: 0
- _ZWrite: 0
m_Colors:
- _Color: {r: 0.13762355, g: 1, b: 0, a: 0.49019608}
- _EmissionColor: {r: 0, g: 0, b: 0, a: 1}
m_BuildTextureStacks: []
@@ -0,0 +1,15 @@
fileFormatVersion: 2
guid: 7b5b45d5c3b714340a1ca8f4c642bd85
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/Rigidbody/Materials/GreenMat.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.52609503, b: 0, a: 1}
- _EmissionColor: {r: 0, g: 0, b: 0, a: 1}
m_BuildTextureStacks: []
@@ -0,0 +1,15 @@
fileFormatVersion: 2
guid: 927568f7fc1cfa14ca78ab4e2ecd8d76
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/Rigidbody/Materials/OrangeMat.mat
uploadId: 866910
@@ -0,0 +1,82 @@
%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: PinkMat
m_Shader: {fileID: 46, guid: 0000000000000000f000000000000000, type: 0}
m_ValidKeywords:
- _ALPHAPREMULTIPLY_ON
m_InvalidKeywords: []
m_LightmapFlags: 4
m_EnableInstancingVariants: 0
m_DoubleSidedGI: 0
m_CustomRenderQueue: 3000
stringTagMap:
RenderType: Transparent
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: 10
- _GlossMapScale: 1
- _Glossiness: 0.5
- _GlossyReflections: 1
- _Metallic: 0
- _Mode: 3
- _OcclusionStrength: 1
- _Parallax: 0.02
- _SmoothnessTextureChannel: 0
- _SpecularHighlights: 1
- _SrcBlend: 1
- _UVSec: 0
- _ZWrite: 0
m_Colors:
- _Color: {r: 1, g: 0, b: 0.41428614, a: 0.49019608}
- _EmissionColor: {r: 0, g: 0, b: 0, a: 1}
m_BuildTextureStacks: []
@@ -0,0 +1,15 @@
fileFormatVersion: 2
guid: 32fce2e1a2cbf23439c57e7b6b853934
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/Rigidbody/Materials/PinkMat.mat
uploadId: 866910
@@ -0,0 +1,82 @@
%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: RedMat
m_Shader: {fileID: 46, guid: 0000000000000000f000000000000000, type: 0}
m_ValidKeywords:
- _ALPHAPREMULTIPLY_ON
m_InvalidKeywords: []
m_LightmapFlags: 4
m_EnableInstancingVariants: 0
m_DoubleSidedGI: 0
m_CustomRenderQueue: 3000
stringTagMap:
RenderType: Transparent
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: 10
- _GlossMapScale: 1
- _Glossiness: 0.5
- _GlossyReflections: 1
- _Metallic: 0
- _Mode: 3
- _OcclusionStrength: 1
- _Parallax: 0.02
- _SmoothnessTextureChannel: 0
- _SpecularHighlights: 1
- _SrcBlend: 1
- _UVSec: 0
- _ZWrite: 0
m_Colors:
- _Color: {r: 1, g: 0.109282315, b: 0, a: 0.49019608}
- _EmissionColor: {r: 0, g: 0, b: 0, a: 1}
m_BuildTextureStacks: []
@@ -0,0 +1,15 @@
fileFormatVersion: 2
guid: 6be79d27c10a3804cbb4a941d6c063ee
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/Rigidbody/Materials/RedMat.mat
uploadId: 866910
@@ -0,0 +1,14 @@
%YAML 1.1
%TAG !u! tag:unity3d.com,2011:
--- !u!134 &13400000
PhysicMaterial:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_Name: Slippery
dynamicFriction: 0.25
staticFriction: 0.25
bounciness: 0
frictionCombine: 0
bounceCombine: 0
@@ -0,0 +1,15 @@
fileFormatVersion: 2
guid: 5279afe67245e4641af070c5a02df994
NativeFormatImporter:
externalObjects: {}
mainObjectFileID: 13400000
userData:
assetBundleName:
assetBundleVariant:
AssetOrigin:
serializedVersion: 1
productId: 207815
packageName: 'FishNet: Networking Evolved'
packageVersion: 4.6.22R
assetPath: Assets/FishNet/Demos/Prediction/Rigidbody/Materials/Slippery.physicMaterial
uploadId: 866910
@@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 7a2f99f17af3b58498907ae93ce16887
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:
@@ -0,0 +1,503 @@
%YAML 1.1
%TAG !u! tag:unity3d.com,2011:
--- !u!1 &562823040
GameObject:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
serializedVersion: 6
m_Component:
- component: {fileID: 562823041}
- component: {fileID: 562823045}
- component: {fileID: 562823044}
- component: {fileID: 562823043}
- component: {fileID: 562823042}
m_Layer: 0
m_Name: RearWheel
m_TagString: Untagged
m_Icon: {fileID: 0}
m_NavMeshLayer: 0
m_StaticEditorFlags: 0
m_IsActive: 1
--- !u!4 &562823041
Transform:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 562823040}
m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
m_LocalPosition: {x: 0, y: 0.32, z: -1.72}
m_LocalScale: {x: 1, y: 2, z: 1}
m_ConstrainProportionsScale: 0
m_Children: []
m_Father: {fileID: 303449598114786577}
m_RootOrder: 2
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
--- !u!33 &562823045
MeshFilter:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 562823040}
m_Mesh: {fileID: 10207, guid: 0000000000000000e000000000000000, type: 0}
--- !u!23 &562823044
MeshRenderer:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 562823040}
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: 2100000, guid: 67717b2583b1d8644a7ed4857736c9cd, type: 2}
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!135 &562823043
SphereCollider:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 562823040}
m_Material: {fileID: 0}
m_IsTrigger: 0
m_Enabled: 1
serializedVersion: 2
m_Radius: 0.5
m_Center: {x: 0, y: 0, z: 0}
--- !u!54 &562823042
Rigidbody:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 562823040}
serializedVersion: 2
m_Mass: 1
m_Drag: 0
m_AngularDrag: 0.05
m_UseGravity: 1
m_IsKinematic: 0
m_Interpolate: 0
m_Constraints: 0
m_CollisionDetection: 0
--- !u!1 &1491914380
GameObject:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
serializedVersion: 6
m_Component:
- component: {fileID: 1491914381}
- component: {fileID: 1491914384}
- component: {fileID: 1491914383}
- component: {fileID: 1491914382}
- component: {fileID: 1491914385}
m_Layer: 0
m_Name: FrontWheel
m_TagString: Untagged
m_Icon: {fileID: 0}
m_NavMeshLayer: 0
m_StaticEditorFlags: 0
m_IsActive: 1
--- !u!4 &1491914381
Transform:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 1491914380}
m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
m_LocalPosition: {x: 0, y: 0.19, z: 1.52}
m_LocalScale: {x: 1, y: 2, z: 1}
m_ConstrainProportionsScale: 0
m_Children: []
m_Father: {fileID: 303449598114786577}
m_RootOrder: 1
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
--- !u!33 &1491914384
MeshFilter:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 1491914380}
m_Mesh: {fileID: 10207, guid: 0000000000000000e000000000000000, type: 0}
--- !u!23 &1491914383
MeshRenderer:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 1491914380}
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: 2100000, guid: c9adb005e24322147b85e0d1ed5fa70e, type: 2}
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!135 &1491914382
SphereCollider:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 1491914380}
m_Material: {fileID: 0}
m_IsTrigger: 0
m_Enabled: 1
serializedVersion: 2
m_Radius: 0.5
m_Center: {x: 0, y: 0, z: 0}
--- !u!54 &1491914385
Rigidbody:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 1491914380}
serializedVersion: 2
m_Mass: 1
m_Drag: 0
m_AngularDrag: 0.05
m_UseGravity: 1
m_IsKinematic: 0
m_Interpolate: 0
m_Constraints: 0
m_CollisionDetection: 0
--- !u!1 &303449598114786579
GameObject:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
serializedVersion: 6
m_Component:
- component: {fileID: 303449598114786577}
- component: {fileID: -4020445548991912745}
- component: {fileID: 201277550}
- component: {fileID: 1517669882}
- component: {fileID: 1517669883}
- component: {fileID: 1517669884}
- component: {fileID: -7879966745361712897}
m_Layer: 0
m_Name: RigidbodyPrediction
m_TagString: Untagged
m_Icon: {fileID: 0}
m_NavMeshLayer: 0
m_StaticEditorFlags: 0
m_IsActive: 1
--- !u!4 &303449598114786577
Transform:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 303449598114786579}
m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
m_LocalPosition: {x: -4.80351, y: 0.18147132, z: 5.430528}
m_LocalScale: {x: 1, y: 0.5, z: 1}
m_ConstrainProportionsScale: 0
m_Children:
- {fileID: 1701588101648257645}
- {fileID: 1491914381}
- {fileID: 562823041}
m_Father: {fileID: 0}
m_RootOrder: 0
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
--- !u!114 &-4020445548991912745
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: 1ad6d36d37ac2b84391a4f7362846abf, type: 3}
m_Name:
m_EditorClassIdentifier:
_componentIndexCache: 0
_addedNetworkObject: {fileID: 201277550}
_networkObjectCache: {fileID: 201277550}
_tickCallbacks: 6
_frontWheelRigidbody: {fileID: 1491914385}
_rearWheelRigidbody: {fileID: 562823042}
_boostDuration: 2
_boostForce: 30
_moveRate: 40
_turnRate: 15
--- !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: -4020445548991912745}
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: 1
_localReconcileCorrectionType: 2
_graphicalObject: {fileID: 0}
_detachGraphicalObject: 0
_enableStateForwarding: 1
_networkTransform: {fileID: 0}
_ownerInterpolation: 2
_ownerSmoothedProperties: 255
_adaptiveInterpolation: 4
_spectatorSmoothedProperties: 255
_spectatorInterpolation: 3
_enableTeleport: 0
_teleportThreshold: 1
<PrefabId>k__BackingField: 2
<SpawnableCollectionId>k__BackingField: 0
<AssetPathHash>k__BackingField: 13573084401941807464
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: 0.5, z: 1}
IsValid: 1
--- !u!54 &1517669882
Rigidbody:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 303449598114786579}
serializedVersion: 2
m_Mass: 1
m_Drag: 0
m_AngularDrag: 0
m_UseGravity: 1
m_IsKinematic: 0
m_Interpolate: 0
m_Constraints: 0
m_CollisionDetection: 0
--- !u!138 &1517669883
FixedJoint:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 303449598114786579}
m_ConnectedBody: {fileID: 1491914385}
m_ConnectedArticulationBody: {fileID: 0}
m_BreakForce: Infinity
m_BreakTorque: Infinity
m_EnableCollision: 1
m_EnablePreprocessing: 1
m_MassScale: 1
m_ConnectedMassScale: 1
--- !u!138 &1517669884
FixedJoint:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 303449598114786579}
m_ConnectedBody: {fileID: 562823042}
m_ConnectedArticulationBody: {fileID: 0}
m_BreakForce: Infinity
m_BreakTorque: Infinity
m_EnableCollision: 1
m_EnablePreprocessing: 1
m_MassScale: 1
m_ConnectedMassScale: 1
--- !u!65 &-7879966745361712897
BoxCollider:
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_Size: {x: 1, y: 1, z: 1}
m_Center: {x: 0, y: 0, z: 0}
--- !u!1 &4223887704561426673
GameObject:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
serializedVersion: 6
m_Component:
- component: {fileID: 1701588101648257645}
- component: {fileID: 4038509139872355570}
- component: {fileID: 948196868863103541}
- component: {fileID: 3171307449894521636}
m_Layer: 0
m_Name: Cube
m_TagString: Untagged
m_Icon: {fileID: 0}
m_NavMeshLayer: 0
m_StaticEditorFlags: 0
m_IsActive: 1
--- !u!4 &1701588101648257645
Transform:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 4223887704561426673}
m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
m_LocalPosition: {x: 0, y: 0, z: 0}
m_LocalScale: {x: 2, y: 1, z: 2}
m_ConstrainProportionsScale: 0
m_Children: []
m_Father: {fileID: 303449598114786577}
m_RootOrder: 0
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
--- !u!33 &4038509139872355570
MeshFilter:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 4223887704561426673}
m_Mesh: {fileID: 10202, guid: 0000000000000000e000000000000000, type: 0}
--- !u!23 &948196868863103541
MeshRenderer:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 4223887704561426673}
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: 2100000, guid: 67717b2583b1d8644a7ed4857736c9cd, type: 2}
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!65 &3171307449894521636
BoxCollider:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 4223887704561426673}
m_Material: {fileID: 0}
m_IsTrigger: 0
m_Enabled: 1
serializedVersion: 2
m_Size: {x: 1, y: 1, z: 1}
m_Center: {x: 0, y: 0, z: 0}
@@ -0,0 +1,14 @@
fileFormatVersion: 2
guid: 26a567abbe21227428f5c3d309d1d73c
PrefabImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:
AssetOrigin:
serializedVersion: 1
productId: 207815
packageName: 'FishNet: Networking Evolved'
packageVersion: 4.6.22R
assetPath: Assets/FishNet/Demos/Prediction/Rigidbody/Prefabs/RigidbodyPrediction.prefab
uploadId: 866910
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,14 @@
fileFormatVersion: 2
guid: 0b7f6237292ee8a4eabe7f955f4a4de5
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:
AssetOrigin:
serializedVersion: 1
productId: 207815
packageName: 'FishNet: Networking Evolved'
packageVersion: 4.6.22R
assetPath: Assets/FishNet/Demos/Prediction/Rigidbody/Rigidbody Prediction Demo.unity
uploadId: 866910
@@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 2b7a81baadcf96f41ad7f4b44f2ca2b8
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:
@@ -0,0 +1,37 @@
using FishNet.Component.Prediction;
using FishNet.Object;
using UnityEngine;
namespace FishNet.Demo.Prediction.Rigidbodies
{
public class Boost : NetworkBehaviour
{
[SerializeField]
private float _rotateRate = 90f;
private void Awake()
{
NetworkTrigger networkTrigger = GetComponent<NetworkTrigger>();
/* No need to unsubscribe this networkTrigger is on this object.
* The subscription will die with the object. */
networkTrigger.OnEnter += NetworkTrigger_OnEnter;
}
private void Update()
{
transform.Rotate(new Vector3(0f, 1f, 0f) * (_rotateRate * Time.deltaTime));
}
private void NetworkTrigger_OnEnter(Collider c)
{
if (!c.transform.root.TryGetComponent(out RigidbodyPrediction rbp))
return;
/* When the vehicle enters this object call set boosted.
* This trigger will invoke if the client enters it after a reconcile as well.
* Because of this, it's not unusual to see enter/exit called many times over a second
* due to the vehicle reconciling and running through the trigger again. */
rbp.BoostHit();
}
}
}
@@ -0,0 +1,18 @@
fileFormatVersion: 2
guid: 3cd8a84b2a9f149449a54fc8110bbfde
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/Rigidbody/Scripts/Boost.cs
uploadId: 866910
@@ -0,0 +1,317 @@
using FishNet.Managing.Timing;
using FishNet.Object;
using FishNet.Object.Prediction;
using FishNet.Transporting;
using FishNet.Utility.Template;
using UnityEngine;
/* Note: the graphical object for this predicted NetworkObject is unset.
* This is because currently the NetworkObject only allows setting of one
* graphical object, but there are three things that move independently.
*
* In version 4.5.8 there will be an option to support multiple graphical objects
* and this demo will be updated. There are plans to release 4.5.8 with only this improvement
* to get the update out fast as possible. */
namespace FishNet.Demo.Prediction.Rigidbodies
{
public class RigidbodyPrediction : TickNetworkBehaviour
{
#region Types.
public struct ReplicateData : IReplicateData
{
public ReplicateData(Vector2 input, bool fire)
{
Input = input;
Fire = fire;
_tick = 0;
}
/// <summary>
/// Current movement directions held.
/// </summary>
public Vector2 Input;
/// <summary>
/// True to fire.
/// </summary>
public bool Fire;
/// <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
{
/// <summary>
/// PredictionRigidbody on the root.
/// </summary>
public PredictionRigidbody Root;
/// <summary>
/// PredictionRigidbody controlling the front wheel.
/// </summary>
public PredictionRigidbody FrontWheel;
/// <summary>
/// PredictionRigidbody controlling the rear wheel.
/// </summary>
public PredictionRigidbody RearWheel;
/// <summary>
/// Tick which the boost started.
/// </summary>
public uint BoostStartTick;
/// <summary>
/// True if to add spring forces next replicate.
/// </summary>
public bool SpringNextReplicate;
/// <summary>
/// Tick is set at runtime. There is no need to manually assign this value.
/// </summary>
private uint _tick;
public ReconcileData(PredictionRigidbody root, PredictionRigidbody frontWheel, PredictionRigidbody rearWheel, uint boostStartTick, bool springNextReplicate)
{
Root = root;
FrontWheel = frontWheel;
RearWheel = rearWheel;
BoostStartTick = boostStartTick;
SpringNextReplicate = springNextReplicate;
_tick = 0;
}
/* You do not need to dispose PredictionRigidbody when used with prediction.
* These references will automatically use pooling to prevent garbage allocations! */
public void Dispose() { }
public uint GetTick() => _tick;
public void SetTick(uint value) => _tick = value;
}
#endregion
[SerializeField]
private Rigidbody _frontWheelRigidbody;
[SerializeField]
private Rigidbody _rearWheelRigidbody;
[SerializeField]
private float _boostDuration = 1f;
[SerializeField]
private float _boostForce = 20f;
[SerializeField]
private float _moveRate = 4f;
[SerializeField]
private float _turnRate = 4f;
/// <summary>
/// Root of the vehicle.
/// </summary>
private PredictionRigidbody _root = new();
/// <summary>
/// Drives turning (front wheels).
/// </summary>
private PredictionRigidbody _frontWheel = new();
/// <summary>
/// Drives acceleration (rear wheels).
/// </summary>
private PredictionRigidbody _rearWheel = new();
/// <summary>
/// Tick which the boost started.
/// </summary>
private uint _boostStartTick = TimeManager.UNSET_TICK;
/// <summary>
/// Tick which the spring started.
/// </summary>
private bool _springNextReplicate;
/// <summary>
/// Tick on the last replicate.
/// </summary>
private uint _lastReplicateTick;
/// <summary>
/// Next tick the controller is allowed to predicted fire.
/// </summary>
private uint _nextAllowedFireTick;
private void Awake()
{
_root.Initialize(GetComponent<Rigidbody>());
_frontWheel.Initialize(_frontWheelRigidbody);
_rearWheel.Initialize(_rearWheelRigidbody);
}
public override void OnStartNetwork()
{
// Rigidbodies need tick and postTick.
SetTickCallbacks(TickCallback.Tick | TickCallback.PostTick);
}
protected override void TimeManager_OnTick()
{
PerformReplicate(BuildMoveData());
}
protected override void TimeManager_OnPostTick()
{
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");
// To keep things simple firing is done by holding left shift.
bool fire = Input.GetKey(KeyCode.LeftShift);
ReplicateData md = new(new(horizontal, vertical), fire);
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(_root, _frontWheel, _rearWheel, _boostStartTick, _springNextReplicate);
PerformReconcile(rd);
}
[Replicate]
private void PerformReplicate(ReplicateData rd, ReplicateState state = ReplicateState.Invalid, Channel channel = Channel.Unreliable)
{
uint rdTick = rd.GetTick();
_lastReplicateTick = rdTick;
/* Since rigidbodies typically carry inertia you do not necessarily need
* to predict in the future; rigidbodies will continue to move along
* the same path anyway.
*
* You can still predict inputs a couple ticks like we did in the
* CharacterController example, if you find doing so creates
* better results. */
Vector3 turningForce = new(rd.Input.x * _turnRate, 0f, 0f);
Vector3 forwardForce = new(0f, 0f, rd.Input.y * _moveRate);
/* If boostStartTick is not unset then a boost is started.
*
* Make sure that the current data tick is at least equal
* to boost tick before adding boost.
* This is done in the scenario a boost happened outside replay,
* we don't want to boost during a replay before the boost started. */
if (_boostStartTick != TimeManager.UNSET_TICK && rdTick >= _boostStartTick)
{
// Add boost to forward force.
forwardForce += new Vector3(0f, 0f, _boostForce);
uint boostTimeToTicks = TimeManager.TimeToTicks(_boostDuration, TickRounding.RoundUp);
// This is when boost will end.
uint endTick = _boostStartTick + boostTimeToTicks;
// Unset boost if tick is met.
if (rdTick >= endTick)
_boostStartTick = TimeManager.UNSET_TICK;
}
if (_springNextReplicate)
{
Vector3 springForce = Vector3.up * 10f;
_root.AddForce(springForce, ForceMode.Impulse);
_springNextReplicate = false;
}
//Convert forwards based on root forward.
Transform rootTransform = _root.Rigidbody.transform;
turningForce = rootTransform.TransformDirection(turningForce);
forwardForce = rootTransform.TransformDirection(forwardForce);
//Flip turning if vehicle is also flipped.
if (rootTransform.up.y <= -0.1f)
turningForce *= -1f;
/* Add turning and forward force.
*
* Notice that forces are NOT multiplied by
* delta. Just like Unity physics, predictionRigidbodies
* do not include delta in calculated forces. */
_frontWheel.AddForce(turningForce);
_rearWheel.AddForce(forwardForce);
_root.Simulate();
_frontWheel.Simulate();
_rearWheel.Simulate();
}
[Reconcile]
private void PerformReconcile(ReconcileData rd, Channel channel = Channel.Unreliable)
{
/* Reconcile boosted start tick. Even though the NetworkTrigger will
* invoke again if a replayed replicate pushes the vehicle through
* the trigger, it will not if the vehicle is in the trigger before the reconcile,
* as well after; since they never left, enter will not be called.*/
_boostStartTick = rd.BoostStartTick;
_springNextReplicate = rd.SpringNextReplicate;
//Reconcile all the rigidbodies.
_root.Reconcile(rd.Root);
_frontWheel.Reconcile(rd.FrontWheel);
_rearWheel.Reconcile(rd.RearWheel);
}
/// <summary>
/// Sets boosted state for a number of ticks.
/// </summary>
public void BoostHit()
{
/* Boost start is set to whatever tick was last replicated.
* Replicate is called every tick, so if the controller hits
* the collider during a replay the tick will be whatever replicate
* is being replayed, if outside a replay it will be the current
* tick.
*
* If owner or server the current tick would be localTick, otherwise
* it will be server tick. */
_boostStartTick = _lastReplicateTick;
}
/// <summary>
/// Add vertical force to the rigidbody next replicate.
/// </summary>
public void SpringHit()
{
//_springNextReplicate = true;
_root.AddForce(Vector3.up * 10f, ForceMode.Impulse);
}
}
}
@@ -0,0 +1,18 @@
fileFormatVersion: 2
guid: 1ad6d36d37ac2b84391a4f7362846abf
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/Rigidbody/Scripts/RigidbodyPrediction.cs
uploadId: 866910
@@ -0,0 +1,37 @@
using FishNet.Component.Prediction;
using FishNet.Object;
using UnityEngine;
namespace FishNet.Demo.Prediction.Rigidbodies
{
public class Spring : NetworkBehaviour
{
[SerializeField]
private float _rotateRate = 90f;
private void Awake()
{
NetworkTrigger networkTrigger = GetComponent<NetworkTrigger>();
/* No need to unsubscribe this networkTrigger is on this object.
* The subscription will die with the object. */
networkTrigger.OnEnter += NetworkTrigger_OnEnter;
}
private void Update()
{
transform.Rotate(new Vector3(0f, 1f, 0f) * (_rotateRate * Time.deltaTime));
}
private void NetworkTrigger_OnEnter(Collider c)
{
if (!c.transform.root.TryGetComponent(out RigidbodyPrediction rbp))
return;
/* When the vehicle enters this object call SpringHit.
* This trigger will invoke if the client enters it after a reconcile as well.
* Because of this, it's not unusual to see enter/exit called many times over a second
* due to the vehicle reconciling and running through the trigger again. */
rbp.SpringHit();
}
}
}
@@ -0,0 +1,18 @@
fileFormatVersion: 2
guid: 444bda66ca6dd6e44b13d36a2cab9c4b
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/Rigidbody/Scripts/Spring.cs
uploadId: 866910
@@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 352b4412576d5134aaf72b172a328810
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:
@@ -0,0 +1,111 @@
fileFormatVersion: 2
guid: 303016f61ea9dd642a6b2812b80f428e
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/Rigidbody/Textures/Stamina_Bar.png
uploadId: 866910