sync
This commit is contained in:
parent
71354308de
commit
d4ba295f07
327
Assets/Resources/SqrBkp.prefab
Normal file
327
Assets/Resources/SqrBkp.prefab
Normal file
|
|
@ -0,0 +1,327 @@
|
|||
%YAML 1.1
|
||||
%TAG !u! tag:unity3d.com,2011:
|
||||
--- !u!1 &295599691903699673
|
||||
GameObject:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
serializedVersion: 6
|
||||
m_Component:
|
||||
- component: {fileID: 5406650049798896926}
|
||||
- component: {fileID: 6874579508060478959}
|
||||
- component: {fileID: 3459790770394357766}
|
||||
- component: {fileID: 4735354123453469529}
|
||||
- component: {fileID: 4952255795263612673}
|
||||
m_Layer: 0
|
||||
m_Name: SqrBkp
|
||||
m_TagString: Untagged
|
||||
m_Icon: {fileID: 0}
|
||||
m_NavMeshLayer: 0
|
||||
m_StaticEditorFlags: 0
|
||||
m_IsActive: 1
|
||||
--- !u!4 &5406650049798896926
|
||||
Transform:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 295599691903699673}
|
||||
serializedVersion: 2
|
||||
m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
|
||||
m_LocalPosition: {x: 0, y: 0, z: 0}
|
||||
m_LocalScale: {x: 1, y: 1, z: 1}
|
||||
m_ConstrainProportionsScale: 0
|
||||
m_Children:
|
||||
- {fileID: 3342671657833137417}
|
||||
- {fileID: 2214332984883492026}
|
||||
m_Father: {fileID: 0}
|
||||
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
|
||||
--- !u!61 &6874579508060478959
|
||||
BoxCollider2D:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 295599691903699673}
|
||||
m_Enabled: 1
|
||||
m_Density: 1
|
||||
m_Material: {fileID: 0}
|
||||
m_IncludeLayers:
|
||||
serializedVersion: 2
|
||||
m_Bits: 0
|
||||
m_ExcludeLayers:
|
||||
serializedVersion: 2
|
||||
m_Bits: 0
|
||||
m_LayerOverridePriority: 0
|
||||
m_ForceSendLayers:
|
||||
serializedVersion: 2
|
||||
m_Bits: 4294967295
|
||||
m_ForceReceiveLayers:
|
||||
serializedVersion: 2
|
||||
m_Bits: 4294967295
|
||||
m_ContactCaptureLayers:
|
||||
serializedVersion: 2
|
||||
m_Bits: 4294967295
|
||||
m_CallbackLayers:
|
||||
serializedVersion: 2
|
||||
m_Bits: 4294967295
|
||||
m_IsTrigger: 0
|
||||
m_UsedByEffector: 0
|
||||
m_UsedByComposite: 0
|
||||
m_Offset: {x: 0, y: 0}
|
||||
m_SpriteTilingProperty:
|
||||
border: {x: 0, y: 0, z: 0, w: 0}
|
||||
pivot: {x: 0, y: 0}
|
||||
oldSize: {x: 0, y: 0}
|
||||
newSize: {x: 0, y: 0}
|
||||
adaptiveTilingThreshold: 0
|
||||
drawMode: 0
|
||||
adaptiveTiling: 0
|
||||
m_AutoTiling: 0
|
||||
serializedVersion: 2
|
||||
m_Size: {x: 0.8, y: 0.8}
|
||||
m_EdgeRadius: 0
|
||||
--- !u!114 &3459790770394357766
|
||||
MonoBehaviour:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 295599691903699673}
|
||||
m_Enabled: 1
|
||||
m_EditorHideFlags: 0
|
||||
m_Script: {fileID: 11500000, guid: 1cb327dda248e37489acbec5dfa62bbc, type: 3}
|
||||
m_Name:
|
||||
m_EditorClassIdentifier:
|
||||
syncDirection: 0
|
||||
syncMode: 0
|
||||
syncInterval: 0
|
||||
skin: {fileID: 11400000, guid: 1296c645b80104448914605af84d2822, type: 2}
|
||||
direction: {x: 1, y: 0}
|
||||
isLocal: 0
|
||||
spriteRenderer: {fileID: 6309712304440343176}
|
||||
myColor: {r: 0.3137255, g: 0.90588236, b: 0.36862746, a: 1}
|
||||
enemyColor: {r: 1, g: 0, b: 0.059296608, a: 1}
|
||||
myBodyColor: {r: 0.16078432, g: 0.5254902, b: 0.20000002, a: 1}
|
||||
enemyBodyColor: {r: 0.5764706, g: 0.098039225, b: 0.10588236, a: 1}
|
||||
isHead: 0
|
||||
--- !u!114 &4735354123453469529
|
||||
MonoBehaviour:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 295599691903699673}
|
||||
m_Enabled: 1
|
||||
m_EditorHideFlags: 0
|
||||
m_Script: {fileID: 11500000, guid: 9b91ecbcc199f4492b9a91e820070131, type: 3}
|
||||
m_Name:
|
||||
m_EditorClassIdentifier:
|
||||
sceneId: 0
|
||||
_assetId: 3639326877
|
||||
serverOnly: 0
|
||||
visibility: 0
|
||||
hasSpawned: 0
|
||||
--- !u!114 &4952255795263612673
|
||||
MonoBehaviour:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 295599691903699673}
|
||||
m_Enabled: 1
|
||||
m_EditorHideFlags: 0
|
||||
m_Script: {fileID: 11500000, guid: 8ff3ba0becae47b8b9381191598957c8, type: 3}
|
||||
m_Name:
|
||||
m_EditorClassIdentifier:
|
||||
syncDirection: 1
|
||||
syncMode: 0
|
||||
syncInterval: 0
|
||||
target: {fileID: 5406650049798896926}
|
||||
syncPosition: 1
|
||||
syncRotation: 1
|
||||
syncScale: 0
|
||||
onlySyncOnChange: 1
|
||||
compressRotation: 1
|
||||
interpolatePosition: 0
|
||||
interpolateRotation: 0
|
||||
interpolateScale: 0
|
||||
coordinateSpace: 0
|
||||
timelineOffset: 1
|
||||
showGizmos: 0
|
||||
showOverlay: 0
|
||||
overlayColor: {r: 0, g: 0, b: 0, a: 0.5}
|
||||
onlySyncOnChangeCorrectionMultiplier: 2
|
||||
useFixedUpdate: 0
|
||||
rotationSensitivity: 0.01
|
||||
positionPrecision: 0.01
|
||||
scalePrecision: 0.01
|
||||
--- !u!1 &2340789509869100348
|
||||
GameObject:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
serializedVersion: 6
|
||||
m_Component:
|
||||
- component: {fileID: 2214332984883492026}
|
||||
- component: {fileID: 7163281116187786196}
|
||||
m_Layer: 0
|
||||
m_Name: block (1)
|
||||
m_TagString: Untagged
|
||||
m_Icon: {fileID: 0}
|
||||
m_NavMeshLayer: 0
|
||||
m_StaticEditorFlags: 0
|
||||
m_IsActive: 0
|
||||
--- !u!4 &2214332984883492026
|
||||
Transform:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 2340789509869100348}
|
||||
serializedVersion: 2
|
||||
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: 5406650049798896926}
|
||||
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
|
||||
--- !u!212 &7163281116187786196
|
||||
SpriteRenderer:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 2340789509869100348}
|
||||
m_Enabled: 1
|
||||
m_CastShadows: 0
|
||||
m_ReceiveShadows: 0
|
||||
m_DynamicOccludee: 1
|
||||
m_StaticShadowCaster: 0
|
||||
m_MotionVectors: 1
|
||||
m_LightProbeUsage: 1
|
||||
m_ReflectionProbeUsage: 1
|
||||
m_RayTracingMode: 0
|
||||
m_RayTraceProcedural: 0
|
||||
m_RenderingLayerMask: 1
|
||||
m_RendererPriority: 0
|
||||
m_Materials:
|
||||
- {fileID: 2100000, guid: a97c105638bdf8b4a8650670310a4cd3, 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: 0
|
||||
m_MinimumChartSize: 4
|
||||
m_AutoUVMaxDistance: 0.5
|
||||
m_AutoUVMaxAngle: 89
|
||||
m_LightmapParameters: {fileID: 0}
|
||||
m_SortingLayerID: 0
|
||||
m_SortingLayer: 0
|
||||
m_SortingOrder: 5
|
||||
m_Sprite: {fileID: 7482667652216324306, guid: 311925a002f4447b3a28927169b83ea6, type: 3}
|
||||
m_Color: {r: 1, g: 1, b: 1, a: 1}
|
||||
m_FlipX: 0
|
||||
m_FlipY: 0
|
||||
m_DrawMode: 0
|
||||
m_Size: {x: 1, y: 1}
|
||||
m_AdaptiveModeThreshold: 0.5
|
||||
m_SpriteTileMode: 0
|
||||
m_WasSpriteAssigned: 1
|
||||
m_MaskInteraction: 0
|
||||
m_SpriteSortPoint: 0
|
||||
--- !u!1 &5408880743873525811
|
||||
GameObject:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
serializedVersion: 6
|
||||
m_Component:
|
||||
- component: {fileID: 3342671657833137417}
|
||||
- component: {fileID: 6309712304440343176}
|
||||
m_Layer: 0
|
||||
m_Name: block
|
||||
m_TagString: Untagged
|
||||
m_Icon: {fileID: 0}
|
||||
m_NavMeshLayer: 0
|
||||
m_StaticEditorFlags: 0
|
||||
m_IsActive: 1
|
||||
--- !u!4 &3342671657833137417
|
||||
Transform:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 5408880743873525811}
|
||||
serializedVersion: 2
|
||||
m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
|
||||
m_LocalPosition: {x: 0.0177, y: 0.0072, z: 0}
|
||||
m_LocalScale: {x: 1, y: 1, z: 0.9}
|
||||
m_ConstrainProportionsScale: 0
|
||||
m_Children: []
|
||||
m_Father: {fileID: 5406650049798896926}
|
||||
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
|
||||
--- !u!212 &6309712304440343176
|
||||
SpriteRenderer:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 5408880743873525811}
|
||||
m_Enabled: 1
|
||||
m_CastShadows: 0
|
||||
m_ReceiveShadows: 0
|
||||
m_DynamicOccludee: 1
|
||||
m_StaticShadowCaster: 0
|
||||
m_MotionVectors: 1
|
||||
m_LightProbeUsage: 1
|
||||
m_ReflectionProbeUsage: 1
|
||||
m_RayTracingMode: 0
|
||||
m_RayTraceProcedural: 0
|
||||
m_RenderingLayerMask: 1
|
||||
m_RendererPriority: 0
|
||||
m_Materials:
|
||||
- {fileID: 2100000, guid: a97c105638bdf8b4a8650670310a4cd3, 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: 0
|
||||
m_MinimumChartSize: 4
|
||||
m_AutoUVMaxDistance: 0.5
|
||||
m_AutoUVMaxAngle: 89
|
||||
m_LightmapParameters: {fileID: 0}
|
||||
m_SortingLayerID: 0
|
||||
m_SortingLayer: 0
|
||||
m_SortingOrder: 5
|
||||
m_Sprite: {fileID: 21300000, guid: 867695b809d154343add975191c8ac2f, type: 3}
|
||||
m_Color: {r: 1, g: 1, b: 1, a: 1}
|
||||
m_FlipX: 0
|
||||
m_FlipY: 0
|
||||
m_DrawMode: 0
|
||||
m_Size: {x: 1, y: 1}
|
||||
m_AdaptiveModeThreshold: 0.5
|
||||
m_SpriteTileMode: 0
|
||||
m_WasSpriteAssigned: 1
|
||||
m_MaskInteraction: 0
|
||||
m_SpriteSortPoint: 0
|
||||
7
Assets/Resources/SqrBkp.prefab.meta
Normal file
7
Assets/Resources/SqrBkp.prefab.meta
Normal file
|
|
@ -0,0 +1,7 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 1f27e187933cc174ea8af8e815961672
|
||||
PrefabImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
|
|
@ -12,7 +12,6 @@ GameObject:
|
|||
- component: {fileID: 6874579508060478959}
|
||||
- component: {fileID: 3459790770394357766}
|
||||
- component: {fileID: 4735354123453469529}
|
||||
- component: {fileID: 4952255795263612673}
|
||||
m_Layer: 0
|
||||
m_Name: Square
|
||||
m_TagString: Untagged
|
||||
|
|
@ -99,7 +98,7 @@ MonoBehaviour:
|
|||
syncInterval: 0
|
||||
skin: {fileID: 11400000, guid: 1296c645b80104448914605af84d2822, type: 2}
|
||||
direction: {x: 1, y: 0}
|
||||
isLocal: 0
|
||||
userId:
|
||||
spriteRenderer: {fileID: 6309712304440343176}
|
||||
myColor: {r: 0.3137255, g: 0.90588236, b: 0.36862746, a: 1}
|
||||
enemyColor: {r: 1, g: 0, b: 0.059296608, a: 1}
|
||||
|
|
@ -123,40 +122,6 @@ MonoBehaviour:
|
|||
serverOnly: 0
|
||||
visibility: 0
|
||||
hasSpawned: 0
|
||||
--- !u!114 &4952255795263612673
|
||||
MonoBehaviour:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 295599691903699673}
|
||||
m_Enabled: 1
|
||||
m_EditorHideFlags: 0
|
||||
m_Script: {fileID: 11500000, guid: 8ff3ba0becae47b8b9381191598957c8, type: 3}
|
||||
m_Name:
|
||||
m_EditorClassIdentifier:
|
||||
syncDirection: 1
|
||||
syncMode: 0
|
||||
syncInterval: 0
|
||||
target: {fileID: 5406650049798896926}
|
||||
syncPosition: 1
|
||||
syncRotation: 1
|
||||
syncScale: 0
|
||||
onlySyncOnChange: 1
|
||||
compressRotation: 1
|
||||
interpolatePosition: 0
|
||||
interpolateRotation: 0
|
||||
interpolateScale: 0
|
||||
coordinateSpace: 0
|
||||
timelineOffset: 1
|
||||
showGizmos: 0
|
||||
showOverlay: 0
|
||||
overlayColor: {r: 0, g: 0, b: 0, a: 0.5}
|
||||
onlySyncOnChangeCorrectionMultiplier: 2
|
||||
useFixedUpdate: 0
|
||||
rotationSensitivity: 0.01
|
||||
positionPrecision: 0.01
|
||||
scalePrecision: 0.01
|
||||
--- !u!1 &2340789509869100348
|
||||
GameObject:
|
||||
m_ObjectHideFlags: 0
|
||||
|
|
|
|||
|
|
@ -3688,7 +3688,7 @@ MonoBehaviour:
|
|||
sendTimeout: 5000
|
||||
receiveTimeout: 20000
|
||||
noDelay: 1
|
||||
sslEnabled: 1
|
||||
sslEnabled: 0
|
||||
sslProtocols: 3072
|
||||
sslCertJson: ./cert.json
|
||||
port: 27777
|
||||
|
|
@ -3706,7 +3706,7 @@ MonoBehaviour:
|
|||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 2131586989}
|
||||
m_Enabled: 0
|
||||
m_Enabled: 1
|
||||
m_EditorHideFlags: 0
|
||||
m_Script: {fileID: 11500000, guid: 6442dc8070ceb41f094e44de0bf87274, type: 3}
|
||||
m_Name:
|
||||
|
|
|
|||
|
|
@ -9,17 +9,22 @@ public class SnakeController : NetworkBehaviour
|
|||
[SyncVar]
|
||||
public string userId;
|
||||
[SyncVar(hook = nameof(OnScoreChange))]
|
||||
public int Score=0;
|
||||
public int Score = 0;
|
||||
public Vector2 startOffset = new Vector3(-10, -10);
|
||||
public float movingInterval = 0.2f;
|
||||
[SyncVar]
|
||||
public Vector2 curDirection = Vector3.right;
|
||||
public List<SnakePiece> snakePieces = new List<SnakePiece>();
|
||||
public List<BendData> bends = new List<BendData>();
|
||||
[SyncVar]
|
||||
private List<BendData> serverBends = new List<BendData>();
|
||||
public GameObject snakePiecePrefab;
|
||||
public int startingLength = 3;
|
||||
|
||||
public Vector2 fieldSize = new Vector2(160, 90);
|
||||
float moveTimer;
|
||||
[SyncVar]
|
||||
private float serverMoveTimer;
|
||||
|
||||
public float topEdge => transform.position.y + fieldSize.y / 2f;
|
||||
public float botEdge => transform.position.y - fieldSize.y / 2f;
|
||||
|
|
@ -31,6 +36,8 @@ public class SnakeController : NetworkBehaviour
|
|||
private List<Vector2> predictedDirections = new List<Vector2>();
|
||||
private float lastServerUpdateTime;
|
||||
private const float MAX_PREDICTION_TIME = 0.5f; // Maximum time to keep predictions
|
||||
private const float PREDICTION_TOLERANCE = 0.1f; // Tolerance for position matching
|
||||
private const float SYNC_THRESHOLD = 1f; // Distance threshold for considering out of sync
|
||||
|
||||
void Start()
|
||||
{
|
||||
|
|
@ -39,27 +46,42 @@ public class SnakeController : NetworkBehaviour
|
|||
ButtonSet.OnLeft += OnLeft;
|
||||
ButtonSet.OnRight += OnRight;
|
||||
|
||||
#if UNITY_EDITOR
|
||||
GameData.user_id = "user" + Random.Range(0, 100);
|
||||
#endif
|
||||
|
||||
if(!isServer&& isLocalPlayer){
|
||||
if (!isServer && isLocalPlayer)
|
||||
{
|
||||
CmdSetUserId(GameData.user_id);
|
||||
}
|
||||
|
||||
if (isLocalPlayer)
|
||||
{
|
||||
lastServerUpdateTime = Time.time;
|
||||
playerType = GameData.isMaster ? PlayerType.Master : PlayerType.Client;
|
||||
playerType = GameData.isMaster ? PlayerType.Master : PlayerType.Client;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
[Command]
|
||||
void CmdSetUserId(string userId){
|
||||
void CmdSetUserId(string userId)
|
||||
{
|
||||
if (GameData.betData == null)
|
||||
{
|
||||
startOffset.y += Random.Range(0, 10);
|
||||
this.userId = userId;
|
||||
|
||||
if(userId == GameData.betData.owner_id){
|
||||
startOffset.y += 10;
|
||||
}
|
||||
this.userId = userId;
|
||||
playerType = userId == GameData.betData.owner_id ? PlayerType.Master : PlayerType.Client;
|
||||
else
|
||||
{
|
||||
if (userId == GameData.betData.owner_id)
|
||||
{
|
||||
startOffset.y += 10;
|
||||
}
|
||||
this.userId = userId;
|
||||
playerType = userId == GameData.betData.owner_id ? PlayerType.Master : PlayerType.Client;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private void OnDestroy()
|
||||
|
|
@ -69,11 +91,43 @@ public class SnakeController : NetworkBehaviour
|
|||
ButtonSet.OnLeft -= OnLeft;
|
||||
ButtonSet.OnRight -= OnRight;
|
||||
}
|
||||
[SyncVar]
|
||||
public bool isKickstarted = false;
|
||||
void OnSnakePiecesChanged(List<NetworkIdentity> oldPieces, List<NetworkIdentity> newPieces)
|
||||
{
|
||||
if (!isClient) return;
|
||||
Debug.Log("Server added a new piece with id: " + newPieces[newPieces.Count - 1].netId);
|
||||
|
||||
// Clear existing pieces
|
||||
foreach (var piece in snakePieces)
|
||||
{
|
||||
if (piece != null)
|
||||
{
|
||||
Destroy(piece.gameObject);
|
||||
}
|
||||
}
|
||||
snakePieces.Clear();
|
||||
|
||||
// Add new pieces
|
||||
foreach (var netId in newPieces)
|
||||
{
|
||||
if (netId != null)
|
||||
{
|
||||
var piece = netId.GetComponent<SnakePiece>();
|
||||
if (piece != null)
|
||||
{
|
||||
snakePieces.Add(piece);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool isKickstarted = false;
|
||||
public void StartGame()
|
||||
{
|
||||
if (!isServer) return;
|
||||
|
||||
snakePieces = new List<SnakePiece>();
|
||||
|
||||
for (int i = 0; i < startingLength; i++)
|
||||
{
|
||||
Vector3 pos = ((Vector2)transform.position - startOffset) - (Vector2.right * i);
|
||||
|
|
@ -82,11 +136,22 @@ public class SnakeController : NetworkBehaviour
|
|||
SnakePiece piece = newPiece.GetComponent<SnakePiece>();
|
||||
piece.userId = userId;
|
||||
snakePieces.Add(piece);
|
||||
RpcAddSnakePiece(piece.netIdentity);
|
||||
}
|
||||
isKickstarted = true;
|
||||
isDead = false;
|
||||
}
|
||||
|
||||
[ClientRpc]
|
||||
void RpcAddSnakePiece(NetworkIdentity netId)
|
||||
{
|
||||
var piece = netId.GetComponent<SnakePiece>();
|
||||
if (piece != null)
|
||||
{
|
||||
snakePieces.Add(piece);
|
||||
}
|
||||
}
|
||||
|
||||
public bool controlling = false;
|
||||
void Update()
|
||||
{
|
||||
|
|
@ -105,7 +170,7 @@ public class SnakeController : NetworkBehaviour
|
|||
}
|
||||
else if (isLocalPlayer)
|
||||
{
|
||||
// Client-side prediction
|
||||
// Client-side prediction for local player
|
||||
if (moveTimer > 0)
|
||||
{
|
||||
moveTimer -= Time.deltaTime;
|
||||
|
|
@ -161,23 +226,29 @@ public class SnakeController : NetworkBehaviour
|
|||
public void AddScore(int amount = 1)
|
||||
{
|
||||
Score += amount;
|
||||
if(isServer){
|
||||
if (isServer)
|
||||
{
|
||||
RpcOnScore();
|
||||
}else{
|
||||
}
|
||||
else
|
||||
{
|
||||
OnScore();
|
||||
}
|
||||
}
|
||||
|
||||
[ClientRpc]
|
||||
void RpcOnScore(){
|
||||
void RpcOnScore()
|
||||
{
|
||||
OnScore();
|
||||
}
|
||||
|
||||
void OnScoreChange(int oldScore, int newScore){
|
||||
void OnScoreChange(int oldScore, int newScore)
|
||||
{
|
||||
NetGameManager.instance.UpdateScore(isLocalPlayer, newScore);
|
||||
}
|
||||
|
||||
void OnScore(){
|
||||
void OnScore()
|
||||
{
|
||||
SFXManager.instance.PlayCrunch();
|
||||
}
|
||||
|
||||
|
|
@ -227,11 +298,14 @@ public class SnakeController : NetworkBehaviour
|
|||
curDirection = moveInputQueue[0];
|
||||
moveInputQueue.RemoveAt(0);
|
||||
|
||||
bends.Add(new BendData()
|
||||
// Add bend to both local and server lists
|
||||
BendData newBend = new BendData()
|
||||
{
|
||||
position = snakePieces[0].transform.position,
|
||||
direction = dir
|
||||
});
|
||||
};
|
||||
bends.Add(newBend);
|
||||
CmdAddBend(newBend);
|
||||
}
|
||||
|
||||
// Store current state for prediction
|
||||
|
|
@ -263,11 +337,12 @@ public class SnakeController : NetworkBehaviour
|
|||
if (bendToRemove != null)
|
||||
{
|
||||
bends.Remove(bendToRemove);
|
||||
CmdRemoveBend(bendToRemove);
|
||||
}
|
||||
}
|
||||
|
||||
// Move head
|
||||
snakePieces[0].transform.position = curPosition + curDirection;
|
||||
snakePieces[0].transform.position = (Vector3)curPosition + (Vector3)curDirection;
|
||||
snakePieces[0].direction = curDirection;
|
||||
snakePieces[0].isHead = true;
|
||||
|
||||
|
|
@ -293,6 +368,12 @@ public class SnakeController : NetworkBehaviour
|
|||
// Store prediction
|
||||
predictedPositions.Add(snakePieces[0].transform.position);
|
||||
predictedDirections.Add(curDirection);
|
||||
|
||||
// Request server sync periodically
|
||||
if (Time.time - lastServerUpdateTime > 0.1f) // Request sync every 100ms
|
||||
{
|
||||
CmdRequestSync();
|
||||
}
|
||||
}
|
||||
|
||||
void Move()
|
||||
|
|
@ -300,123 +381,163 @@ public class SnakeController : NetworkBehaviour
|
|||
if (moveTimer > 0)
|
||||
{
|
||||
moveTimer -= Time.deltaTime;
|
||||
return;
|
||||
}
|
||||
else
|
||||
|
||||
moveTimer = movingInterval;
|
||||
if (moveInputQueue.Count > 0)
|
||||
{
|
||||
moveTimer = movingInterval;
|
||||
if (moveInputQueue.Count > 0)
|
||||
Vector2 dir = Vector2.zero;
|
||||
if (curDirection.x != 0)
|
||||
{
|
||||
Vector2 dir = Vector2.zero;
|
||||
if (curDirection.x != 0)
|
||||
{
|
||||
dir = new Vector2(-curDirection.x, moveInputQueue[0].y);
|
||||
}
|
||||
else
|
||||
{
|
||||
dir = new Vector2(moveInputQueue[0].x, -curDirection.y);
|
||||
}
|
||||
curDirection = moveInputQueue[0];
|
||||
moveInputQueue.RemoveAt(0);
|
||||
|
||||
bends.Add(new BendData()
|
||||
{
|
||||
position = snakePieces[0].transform.position,
|
||||
direction = dir
|
||||
});
|
||||
dir = new Vector2(-curDirection.x, moveInputQueue[0].y);
|
||||
}
|
||||
|
||||
Vector2 curPosition = snakePieces[0].transform.position;
|
||||
Vector2 lastPosition = snakePieces[snakePieces.Count - 1].transform.position;
|
||||
|
||||
for (int i = snakePieces.Count - 1; i > 0; i--)
|
||||
else
|
||||
{
|
||||
Vector3 dir = (snakePieces[i - 1].transform.position - snakePieces[i].transform.position).normalized;
|
||||
snakePieces[i].direction = dir;
|
||||
snakePieces[i].isHead = false;
|
||||
snakePieces[i].transform.position = snakePieces[i - 1].transform.position;
|
||||
dir = new Vector2(moveInputQueue[0].x, -curDirection.y);
|
||||
}
|
||||
curDirection = moveInputQueue[0];
|
||||
moveInputQueue.RemoveAt(0);
|
||||
|
||||
BendData bendToRemove = null;
|
||||
foreach (BendData bend in bends)
|
||||
// Add bend to both local and server lists
|
||||
BendData newBend = new BendData()
|
||||
{
|
||||
position = snakePieces[0].transform.position,
|
||||
direction = dir
|
||||
};
|
||||
bends.Add(newBend);
|
||||
CmdAddBend(newBend);
|
||||
}
|
||||
|
||||
Vector2 curPosition = snakePieces[0].transform.position;
|
||||
Vector2 lastPosition = snakePieces[snakePieces.Count - 1].transform.position;
|
||||
|
||||
// Update snake pieces
|
||||
for (int i = snakePieces.Count - 1; i > 0; i--)
|
||||
{
|
||||
Vector3 dir = (snakePieces[i - 1].transform.position - snakePieces[i].transform.position).normalized;
|
||||
snakePieces[i].direction = dir;
|
||||
snakePieces[i].isHead = false;
|
||||
snakePieces[i].transform.position = snakePieces[i - 1].transform.position;
|
||||
|
||||
BendData bendToRemove = null;
|
||||
foreach (BendData bend in bends)
|
||||
{
|
||||
if (bend.position == snakePieces[i].transform.position)
|
||||
{
|
||||
if (bend.position == snakePieces[i].transform.position)
|
||||
snakePieces[i].direction = bend.direction;
|
||||
if (i == snakePieces.Count - 1)
|
||||
{
|
||||
snakePieces[i].direction = bend.direction;
|
||||
if (i == snakePieces.Count - 1)
|
||||
{
|
||||
bendToRemove = bend;
|
||||
}
|
||||
break;
|
||||
bendToRemove = bend;
|
||||
}
|
||||
}
|
||||
|
||||
if (bendToRemove != null)
|
||||
{
|
||||
bends.Remove(bendToRemove);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (queueNewPiece)
|
||||
if (bendToRemove != null)
|
||||
{
|
||||
GameObject newPiece = Instantiate(snakePiecePrefab, lastPosition, Quaternion.identity);
|
||||
NetworkServer.Spawn(newPiece);
|
||||
SnakePiece piece = newPiece.GetComponent<SnakePiece>();
|
||||
piece.userId = userId;
|
||||
snakePieces.Add(piece);
|
||||
SFXManager.instance.PlayCrunch();
|
||||
AddScore();
|
||||
bends.Remove(bendToRemove);
|
||||
CmdRemoveBend(bendToRemove);
|
||||
}
|
||||
}
|
||||
|
||||
queueNewPiece = false;
|
||||
if (queueNewPiece)
|
||||
{
|
||||
GameObject newPiece = Instantiate(snakePiecePrefab, lastPosition, Quaternion.identity);
|
||||
NetworkServer.Spawn(newPiece);
|
||||
SnakePiece piece = newPiece.GetComponent<SnakePiece>();
|
||||
piece.userId = userId;
|
||||
snakePieces.Add(piece);
|
||||
RpcAddSnakePiece(piece.netIdentity);
|
||||
SFXManager.instance.PlayCrunch();
|
||||
AddScore();
|
||||
|
||||
queueNewPiece = false;
|
||||
}
|
||||
|
||||
// Move head
|
||||
snakePieces[0].transform.position = (Vector3)curPosition + (Vector3)curDirection;
|
||||
snakePieces[0].direction = curDirection;
|
||||
snakePieces[0].isHead = true;
|
||||
|
||||
// Handle wrapping
|
||||
if (snakePieces[0].transform.position.x > rightEdge)
|
||||
{
|
||||
snakePieces[0].transform.position = new Vector2(leftEdge, snakePieces[0].transform.position.y);
|
||||
}
|
||||
else if (snakePieces[0].transform.position.x < leftEdge)
|
||||
{
|
||||
snakePieces[0].transform.position = new Vector2(rightEdge, snakePieces[0].transform.position.y);
|
||||
}
|
||||
|
||||
if (snakePieces[0].transform.position.y > topEdge)
|
||||
{
|
||||
snakePieces[0].transform.position = new Vector2(snakePieces[0].transform.position.x, botEdge);
|
||||
}
|
||||
else if (snakePieces[0].transform.position.y < botEdge)
|
||||
{
|
||||
snakePieces[0].transform.position = new Vector2(snakePieces[0].transform.position.x, topEdge);
|
||||
}
|
||||
|
||||
// After server movement, send state to clients
|
||||
if (isServer)
|
||||
{
|
||||
Vector2[] positions = new Vector2[snakePieces.Count];
|
||||
Vector2[] directions = new Vector2[snakePieces.Count];
|
||||
|
||||
for (int i = 0; i < snakePieces.Count; i++)
|
||||
{
|
||||
positions[i] = snakePieces[i].transform.position;
|
||||
directions[i] = snakePieces[i].direction;
|
||||
}
|
||||
|
||||
snakePieces[0].transform.position = curPosition + curDirection;
|
||||
snakePieces[0].direction = curDirection;
|
||||
snakePieces[0].isHead = true;
|
||||
|
||||
if (snakePieces[0].transform.position.x > rightEdge)
|
||||
{
|
||||
snakePieces[0].transform.position = new Vector2(leftEdge, snakePieces[0].transform.position.y);
|
||||
}
|
||||
else if (snakePieces[0].transform.position.x < leftEdge)
|
||||
{
|
||||
snakePieces[0].transform.position = new Vector2(rightEdge, snakePieces[0].transform.position.y);
|
||||
}
|
||||
|
||||
if (snakePieces[0].transform.position.y > topEdge)
|
||||
{
|
||||
snakePieces[0].transform.position = new Vector2(snakePieces[0].transform.position.x, botEdge);
|
||||
}
|
||||
else if (snakePieces[0].transform.position.y < botEdge)
|
||||
{
|
||||
snakePieces[0].transform.position = new Vector2(snakePieces[0].transform.position.x, topEdge);
|
||||
}
|
||||
|
||||
// After server movement, send state to clients
|
||||
if (isServer)
|
||||
{
|
||||
Vector2[] positions = new Vector2[snakePieces.Count];
|
||||
Vector2[] directions = new Vector2[snakePieces.Count];
|
||||
|
||||
for (int i = 0; i < snakePieces.Count; i++)
|
||||
{
|
||||
positions[i] = snakePieces[i].transform.position;
|
||||
directions[i] = snakePieces[i].direction;
|
||||
}
|
||||
|
||||
RpcReconcileState(positions, directions);
|
||||
}
|
||||
RpcReconcileState(positions, directions, serverMoveTimer);
|
||||
}
|
||||
}
|
||||
|
||||
[ClientRpc]
|
||||
void RpcReconcileState(Vector2[] serverPositions, Vector2[] serverDirections)
|
||||
[Command]
|
||||
void CmdRequestSync()
|
||||
{
|
||||
Vector2[] positions = new Vector2[snakePieces.Count];
|
||||
Vector2[] directions = new Vector2[snakePieces.Count];
|
||||
|
||||
for (int i = 0; i < snakePieces.Count; i++)
|
||||
{
|
||||
positions[i] = snakePieces[i].transform.position;
|
||||
directions[i] = snakePieces[i].direction;
|
||||
}
|
||||
|
||||
RpcReconcileState(positions, directions, serverMoveTimer);
|
||||
}
|
||||
|
||||
[ClientRpc]
|
||||
void RpcReconcileState(Vector2[] serverPositions, Vector2[] serverDirections, float serverTimer)
|
||||
{
|
||||
if (!isLocalPlayer && !isServer)
|
||||
{
|
||||
// For non-local players, directly update positions from server
|
||||
for (int i = 0; i < snakePieces.Count; i++)
|
||||
{
|
||||
if (i < serverPositions.Length)
|
||||
{
|
||||
snakePieces[i].transform.position = serverPositions[i];
|
||||
snakePieces[i].direction = serverDirections[i];
|
||||
snakePieces[i].isHead = (i == 0);
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
if (!isLocalPlayer) return;
|
||||
|
||||
// Sync move timer with server
|
||||
moveTimer = serverTimer;
|
||||
|
||||
// Find the oldest prediction that matches the server state
|
||||
int matchIndex = -1;
|
||||
for (int i = 0; i < predictedPositions.Count; i++)
|
||||
{
|
||||
if (Vector2.Distance(predictedPositions[i], serverPositions[0]) < 0.1f)
|
||||
if (Vector2.Distance(predictedPositions[i], serverPositions[0]) < PREDICTION_TOLERANCE)
|
||||
{
|
||||
matchIndex = i;
|
||||
break;
|
||||
|
|
@ -431,15 +552,38 @@ public class SnakeController : NetworkBehaviour
|
|||
}
|
||||
else
|
||||
{
|
||||
// No match found, reset to server state
|
||||
predictedPositions.Clear();
|
||||
predictedDirections.Clear();
|
||||
|
||||
// Update snake pieces to match server state
|
||||
// Check if we're significantly out of sync
|
||||
bool needsSync = false;
|
||||
float maxDist = 0;
|
||||
for (int i = 0; i < snakePieces.Count; i++)
|
||||
{
|
||||
snakePieces[i].transform.position = serverPositions[i];
|
||||
snakePieces[i].direction = serverDirections[i];
|
||||
if (i < serverPositions.Length)
|
||||
{
|
||||
float distance = Vector2.Distance(snakePieces[i].transform.position, serverPositions[i]);
|
||||
if (distance > SYNC_THRESHOLD)
|
||||
{
|
||||
maxDist = Mathf.Max(maxDist, distance);
|
||||
needsSync = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (needsSync)
|
||||
{
|
||||
Debug.Log("Syncing local player, max dist: " + maxDist);
|
||||
// Only update positions if significantly out of sync
|
||||
for (int i = 0; i < snakePieces.Count; i++)
|
||||
{
|
||||
if (i < serverPositions.Length)
|
||||
{
|
||||
snakePieces[i].transform.position = serverPositions[i];
|
||||
snakePieces[i].direction = serverDirections[i];
|
||||
snakePieces[i].isHead = (i == 0);
|
||||
}
|
||||
}
|
||||
// Clear predictions after sync
|
||||
predictedPositions.Clear();
|
||||
predictedDirections.Clear();
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -487,6 +631,37 @@ public class SnakeController : NetworkBehaviour
|
|||
}
|
||||
}
|
||||
|
||||
[Command]
|
||||
void CmdAddBend(BendData bend)
|
||||
{
|
||||
serverBends.Add(bend);
|
||||
RpcAddBend(bend);
|
||||
}
|
||||
|
||||
[Command]
|
||||
void CmdRemoveBend(BendData bend)
|
||||
{
|
||||
serverBends.Remove(bend);
|
||||
RpcRemoveBend(bend);
|
||||
}
|
||||
|
||||
[ClientRpc]
|
||||
void RpcAddBend(BendData bend)
|
||||
{
|
||||
if (!isLocalPlayer)
|
||||
{
|
||||
bends.Add(bend);
|
||||
}
|
||||
}
|
||||
|
||||
[ClientRpc]
|
||||
void RpcRemoveBend(BendData bend)
|
||||
{
|
||||
if (!isLocalPlayer)
|
||||
{
|
||||
bends.Remove(bend);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
[System.Serializable]
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user