Trail sync with client predictions
This commit is contained in:
80
Assets/Game/Scripts/Minigame/NetworkTrail.cs
Normal file
80
Assets/Game/Scripts/Minigame/NetworkTrail.cs
Normal file
@@ -0,0 +1,80 @@
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
using Mirror;
|
||||
|
||||
public class NetworkTrail : NetworkBehaviour
|
||||
{
|
||||
public TrailRenderer trail;
|
||||
public LineRenderer line;
|
||||
public bool enableValidation = true;
|
||||
public int maxDetourPoints = 1;
|
||||
public float DetourThreshold = 1;
|
||||
public int Detours;
|
||||
|
||||
public Vector3[] positions;
|
||||
|
||||
void Start()
|
||||
{
|
||||
//trail.gameObject.SetActive(isServer);
|
||||
line.gameObject.SetActive(!isServer);
|
||||
line.transform.parent=null;
|
||||
line.transform.position =Vector3.zero;
|
||||
}
|
||||
|
||||
// Update is called once per frame
|
||||
void Update()
|
||||
{
|
||||
if(isServer){
|
||||
positions = new Vector3[trail.positionCount];
|
||||
trail.GetPositions(positions);
|
||||
RpcUpdatePositions(positions);
|
||||
}else{
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
[ClientRpc]
|
||||
void RpcUpdatePositions(Vector3[] Positions){
|
||||
if(!enableValidation){return;}
|
||||
positions = Positions;
|
||||
line.positionCount = positions.Length;
|
||||
line.SetPositions(positions);
|
||||
|
||||
//Validate With Trail
|
||||
Vector3[] localPositions = new Vector3[trail.positionCount];
|
||||
trail.GetPositions(localPositions);
|
||||
Detours = 0;
|
||||
for(int i=0; i < Positions.Length; i++){
|
||||
bool pointValidated = false;
|
||||
for(int j=1; j < 3; j++){
|
||||
try{
|
||||
if(isCloseEnough(Positions[i], localPositions[i+j])){
|
||||
pointValidated = true;
|
||||
break;
|
||||
}
|
||||
if(isCloseEnough(Positions[i], localPositions[i-j])){
|
||||
pointValidated = true;
|
||||
break;
|
||||
}
|
||||
|
||||
}catch{
|
||||
//No local position, Hence, no validation
|
||||
}
|
||||
}
|
||||
if(!pointValidated){
|
||||
Detours++;
|
||||
}
|
||||
}
|
||||
|
||||
if(Detours > maxDetourPoints){
|
||||
//Too much detours, Set back to servers data
|
||||
trail.SetPositions(Positions);
|
||||
}
|
||||
}
|
||||
|
||||
bool isCloseEnough(Vector3 a, Vector3 b){
|
||||
return Vector3.Distance(a,b) < DetourThreshold;
|
||||
}
|
||||
}
|
||||
11
Assets/Game/Scripts/Minigame/NetworkTrail.cs.meta
Normal file
11
Assets/Game/Scripts/Minigame/NetworkTrail.cs.meta
Normal file
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 661698fa54f409f4d8251cfdd48d8f51
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
17
Assets/Game/Scripts/Minigame/SceneDataHolder.cs
Normal file
17
Assets/Game/Scripts/Minigame/SceneDataHolder.cs
Normal file
@@ -0,0 +1,17 @@
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
|
||||
public class SceneDataHolder : MonoBehaviour
|
||||
{
|
||||
public Transform trailCollidersParent;
|
||||
void Awake()
|
||||
{
|
||||
SceneData.holder = this;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public static class SceneData{
|
||||
public static SceneDataHolder holder;
|
||||
}
|
||||
11
Assets/Game/Scripts/Minigame/SceneDataHolder.cs.meta
Normal file
11
Assets/Game/Scripts/Minigame/SceneDataHolder.cs.meta
Normal file
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 050f3527cd45bfc8d862ebc6d9942cc8
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -14,6 +14,7 @@ public class SpaceshipController : NetworkBehaviour
|
||||
|
||||
[Header("Client Prediction")]
|
||||
public SortedDictionary<int, StatePayload> serverStateBuffer = new SortedDictionary<int, StatePayload>();
|
||||
public Vector3 DetourError = new Vector3(0,0.2f,0);
|
||||
public Vector3 Detour = Vector3.zero;
|
||||
public Quaternion RotationDetour = Quaternion.identity;
|
||||
public float DetourCorrectionFactor = 0.5f;
|
||||
@@ -122,7 +123,8 @@ public class SpaceshipController : NetworkBehaviour
|
||||
newRotation = Quaternion.Lerp(newRotation, getTurnAngle(input), turningSmoothFactor * input.magnitude);
|
||||
}
|
||||
|
||||
targetPosition = newPosition;
|
||||
targetPosition = newPosition - DetourError;
|
||||
|
||||
targetRotation = newRotation;
|
||||
}
|
||||
|
||||
@@ -156,7 +158,7 @@ public class SpaceshipController : NetworkBehaviour
|
||||
payloadToCompare = lastServerState;
|
||||
if (lastServerState.Time < time)
|
||||
{
|
||||
Debug.Log("Server doesn't have that data yet\nYou asked for " + time + " best I can do is " + lastServerState.Time);
|
||||
// Debug.Log("Server doesn't have that data yet\nYou asked for " + time + " best I can do is " + lastServerState.Time);
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -185,7 +187,7 @@ public class SpaceshipController : NetworkBehaviour
|
||||
}
|
||||
else
|
||||
{
|
||||
Debug.Log($"RB : {positionDiff.magnitude} [{timeDiff}ms]");
|
||||
// Debug.Log($"RB : {positionDiff.magnitude} [{timeDiff}ms]");
|
||||
RpcRubberBand(joyInput, serverStateBuffer.Values.Last().Position, serverStateBuffer.Values.Last().Rotation, trailMgr.positions, timeInMillis);
|
||||
}
|
||||
|
||||
@@ -231,7 +233,7 @@ public class SpaceshipController : NetworkBehaviour
|
||||
// Vector3 newPosition = position + new Vector3(0, movingSpeed * );
|
||||
|
||||
// Vector3 newPosition = position;
|
||||
Detour = newPosition - transform.position;
|
||||
Detour = newPosition - transform.position - DetourError;
|
||||
|
||||
// RotationDetour = rotation;
|
||||
RotationDetour = Quaternion.Inverse(transform.rotation) * newRotation;
|
||||
|
||||
@@ -5,12 +5,13 @@ using UnityEngine;
|
||||
public class TrailCollider : MonoBehaviour
|
||||
{
|
||||
public Color gizmoColor = Color.red;
|
||||
public TrailMgr trailMgr;
|
||||
public float radius;
|
||||
void Update(){
|
||||
RaycastHit2D hit = Physics2D.CircleCast(transform.position, radius, Vector2.up);
|
||||
if(hit.collider!=null){
|
||||
if(hit.transform == transform.root){return;} // <-- avoid eating myself
|
||||
transform.root.GetComponent<TrailMgr>().OnColliderHit(hit);
|
||||
if(hit.transform.root == trailMgr.transform){return;} // <-- avoid eating myself
|
||||
trailMgr.OnColliderHit(hit);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,26 +1,20 @@
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
using Mirror;
|
||||
|
||||
public class TrailMgr : NetworkBehaviour
|
||||
public class TrailMgr : MonoBehaviour
|
||||
{
|
||||
public TrailRenderer trail;
|
||||
public LineRenderer line;
|
||||
public Vector3[] positions;
|
||||
public Transform trailPoolParent;
|
||||
public GameObject trailColliderObj;
|
||||
public List<GameObject> trailsPool;
|
||||
|
||||
void Start(){
|
||||
trail.gameObject.SetActive(isServer);
|
||||
}
|
||||
|
||||
// Update is called once per frame
|
||||
void Update()
|
||||
{
|
||||
if(!isServer){return;}
|
||||
|
||||
void Update(){
|
||||
positions = new Vector3[trail.positionCount];
|
||||
int length = trail.GetPositions(positions);
|
||||
if(length > trailsPool.Count){
|
||||
@@ -28,6 +22,8 @@ public class TrailMgr : NetworkBehaviour
|
||||
int missingCount = length - trailsPool.Count;
|
||||
for(int i =0; i < missingCount; i++){
|
||||
GameObject newTrail = Instantiate(trailColliderObj, trailPoolParent);
|
||||
// Debug.Log("Spawned new trail obj " + newTrail.name);
|
||||
newTrail.GetComponent<TrailCollider>().trailMgr = this;
|
||||
trailsPool.Add(newTrail);
|
||||
}
|
||||
}
|
||||
@@ -39,17 +35,12 @@ public class TrailMgr : NetworkBehaviour
|
||||
trailsPool[i].SetActive(false);
|
||||
}
|
||||
}
|
||||
RpcUpdateTrail(positions);
|
||||
}
|
||||
|
||||
[ClientRpc]
|
||||
void RpcUpdateTrail(Vector3[] new_positions){
|
||||
positions = new_positions;
|
||||
line.SetPositions(positions);
|
||||
}
|
||||
|
||||
|
||||
public void OnColliderHit(RaycastHit2D hit){
|
||||
return;
|
||||
Debug.Log($"{hit.collider.name} got hit by my trail");
|
||||
Destroy(hit.transform.gameObject);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user