Trail sync with client predictions

This commit is contained in:
2022-06-22 19:54:18 +05:30
parent b450cfdf36
commit a18c7028c4
19 changed files with 232 additions and 28 deletions

View 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;
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 661698fa54f409f4d8251cfdd48d8f51
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View 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;
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 050f3527cd45bfc8d862ebc6d9942cc8
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -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;

View File

@@ -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);
}
}

View File

@@ -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);
}