/// <summary> /// Updates local client version of the ball, mixing server data and locally simulated data /// </summary> void Update_ClientPredict_Lerp() { if (m_PacketBuffer.Count == 0) { return; } // Estimated Result given by server data Vector3 predictionResult = Vector3.zero; Projectile2DState lastPackage = GetLastPackage(); double timeSinceLastPackageState = PhotonNetwork.time - lastPackage.stateTime; predictionResult = CalculateProjectilePos(lastPackage.Position3() + Vector3.up * .5f, lastPackage.Direction3(), MovementSpeed, (float)timeSinceLastPackageState);// + Time.deltaTime); // Locally Simulated result Vector3 simulationResult = CalculateProjectilePos(transform.position, Direction, MovementSpeed, Time.deltaTime); Direction.y = 0; Direction.Normalize(); // blend the 2 results float epsillon = (predictionResult - simulationResult).magnitude; float maxEpsillon = 1f; Vector3 blendedPosition = Vector3.Lerp(simulationResult, predictionResult, epsillon / maxEpsillon); //Vector3 blendedDirection = Vector3.Lerp(Direction, lastPackage.Direction3(), epsillon / maxEpsillon); // to not blend yet transform.position = blendedPosition; Rigidbody rbdy = GetComponent <Rigidbody>(); rbdy.velocity = Vector3.zero; Direction = lastPackage.Direction3(); //rbdy.MovePosition(blendedPosition); }
void DrawPackageInfo(Projectile2DState pack, Color col) { Debug.DrawLine(pack.Position3() + Vector3.up, pack.Position3() + pack.Direction3() + Vector3.up , col, 1); }
void Update_ClientPredict() { // get most recent package and calculate position from there? if (m_PacketBuffer.Count > 0) { // init variables Projectile2DState currentPackage = GetPackageBefore(PhotonNetwork.time - ArticifialDelay); Rigidbody rbdy = GetComponent <Rigidbody>(); Vector3 clientPos = transform.position; Vector3 serverPos = currentPackage.Position3(); //Vector3 clientDir = Direction; Vector3 serverDir = currentPackage.Direction3(); double clientTime = PhotonNetwork.time - ArticifialDelay; double serverTime = currentPackage.stateTime; rbdy.velocity = Vector3.zero; // override unity's ridigbody Vector3 currentPos = clientPos; float dTime = Time.deltaTime; if (m_lastUsedPacket.stateTime.CompareTo(currentPackage.stateTime) == -1) { // new packet is used for the first time float packAge = (float)(clientTime - serverTime); // if collision is imminent, .. don't overwrite? // imminent = within packAge RaycastHit[] hitinfo = Physics.SphereCastAll(serverPos, .75f, serverDir, packAge * MovementSpeed, LayerMask.GetMask("WorldCollision")); if (hitinfo.Length != 0) { // this means a hit would have happened between ServerTime and Now , // todo: predict clientpos further, or leave it like this Debug.LogWarning("predicted a hit"); } else { currentPos = CalculateProjectilePos(serverPos, serverDir, MovementSpeed, packAge); } //dTime = (float)(clientTime - serverTime); // <--- THIS IS WRONG!, this is the time to the current frame! // calculate where the projecitle SHOULD BE! } // prediction code: Vector3 nextBallPos = CalculateProjectilePos(currentPos, Direction, MovementSpeed, dTime); // Using rigidbody;'s move, I get physix calculations for everything I do, so this is prefered rbdy.MovePosition(nextBallPos); nextPosition = nextBallPos; previousPosition = currentPos; m_lastUsedPacket = currentPackage; } }
void DrawPackageInfo(Projectile2DState pack, Color col) { Debug.DrawLine(pack.Position3() + Vector3.up, pack.Position3() + pack.Direction3() + Vector3.up, col, 1); }