netcode good condition

This commit is contained in:
2023-04-19 21:38:28 +03:00
parent 3b4d50e75e
commit 353db087a6
8 changed files with 403 additions and 79 deletions

View File

@@ -127,7 +127,8 @@ namespace Game
return;
//PlayerInputState inputState = new PlayerInputState(frame, viewDeltaXYMoveForwardRight.X, viewDeltaXYMoveForwardRight.Y, viewDeltaXYMoveForwardRight.Z, viewDeltaXYMoveForwardRight.W, attacking, jumping);
playerInputNetwork.currentState.input = inputState;
//playerInputNetwork.currentState.input = inputState;
playerInputNetwork.SetState(inputState.frame, inputState);
}
public void SetPosition(Float3 newPosition)

View File

@@ -76,6 +76,8 @@ namespace Game
public Quaternion orientation;
public Float3 viewAngles; // yaw, pitch, roll
public float lastJumpTime;
public int numJumps;
public bool jumped;
}
[StructLayout(LayoutKind.Sequential)]
@@ -106,8 +108,8 @@ namespace Game
public virtual void OnEndFrame()
{
Console.Print("recorded frame " + frame);
currentState.input.frame = frame;
//Console.Print("recorded frame " + frame);
states[frame % 120] = currentState;
/*ulong oldest = ulong.MaxValue;
@@ -116,10 +118,14 @@ namespace Game
oldestFrame = oldest;*/
frame++;
currentState.input.frame = frame;
}
public virtual void RecordCurrentActorState(PlayerActorState actorState)
{
if (actorState.position.Length <= 0.01)
Console.Print("wrong recorded position?");
currentState.actor = actorState;
}
public bool GetState(ulong frame, out PlayerInputState inputState, out PlayerActorState actorState)
@@ -137,6 +143,14 @@ namespace Game
return true;
}
public void SetState(ulong frame, PlayerInputState inputState)
{
int frameIndex = (int)frame % 120;
states[frameIndex].input = inputState;
states[frameIndex].input.frame = frame;
states[frameIndex].actor = new PlayerActorState();
}
public void SetState(ulong frame, PlayerInputState inputState, PlayerActorState actorState)
{
int frameIndex = (int)frame % 120;

View File

@@ -116,9 +116,7 @@ namespace Game
if (!IsRecording)
return;
if (actorState.position.Length <= 0.01)
Console.Print("wrong recorded position?");
currentState.actor = actorState;
base.RecordCurrentActorState(actorState);
}
public void FlushDemo()

View File

@@ -86,17 +86,17 @@ namespace Game
//public int currentInputFrame;
//private int currentInputFrame2;
private Float3 currentVelocity;
public Float3 currentVelocity;
public PlayerInput input;
//private bool physicsInteractions = false;
private bool jumped;
public bool jumped;
//private int lastInputFrame;
private float lastJumped = -1f;
public float lastJumped = -1f;
private float lastLanded = -1f;
private int numJumps;
public int numJumps;
private float simulationTime = 0f;
[ReadOnly] public bool onGround;
@@ -104,8 +104,7 @@ namespace Game
private Actor cameraHolder;
private PlayerActor playerActor;
private Actor rootActor;
private float startupTime;
public Actor rootActor;
public Float3 viewAngles;
private Float3 viewAnglesLastFrame;
@@ -164,8 +163,6 @@ namespace Game
//rigidBody.CollisionEnter += OnCollisionEnter;
//rigidBody.TriggerEnter += OnTriggerEnter;
//rigidBody.TriggerExit += OnTriggerExit;
startupTime = Time.TimeSinceStartup;
}
public void SetInput(uint playerId)
@@ -279,23 +276,31 @@ namespace Game
viewRoll = actorState.viewRoll;
}*/
PlayerInputState inputState = input.GetCurrentInputState();
//if (inputState.viewDeltaX != 0 || inputState.viewDeltaY != 0)
// inputState = inputState;
viewAngles = viewAnglesLastFrame;
ApplyInputToCamera(inputState);
input.RecordCurrentActorState(new PlayerActorState
if (input is not PlayerInputNetwork)
{
position = Actor.Position,
velocity = currentVelocity,
orientation = rootActor.Orientation,
viewAngles = viewAngles,
lastJumpTime = lastJumped,
//viewAngles = new Float3(viewAngles.Y, viewAngles.X, viewAngles.Z)
});
PlayerInputState inputState = input.GetCurrentInputState();
//if (inputState.viewDeltaX != 0 || inputState.viewDeltaY != 0)
// inputState = inputState;
ApplyInputToCamera(inputState);
input.RecordCurrentActorState(new PlayerActorState
{
position = Actor.Position,
velocity = currentVelocity,
orientation = rootActor.Orientation,
viewAngles = viewAngles,
lastJumpTime = lastJumped,
numJumps = numJumps,
jumped = jumped,
//viewAngles = new Float3(viewAngles.Y, viewAngles.X, viewAngles.Z)
});
}
/*input.RecordCurrentActorState(new PlayerActorState()
{
@@ -372,6 +377,106 @@ namespace Game
}*/
}
}
else if (input is PlayerInputNetwork)
{
#if false
bool canpredict = true;
if (false && input.Predict && GameModeManager.ClientFrame > 0 && GameModeManager.ServerFrame > 0)
{
ulong maxFrame = /*NetworkManager.IsServer ? GameModeManager.playerLastReceivedFrames[PlayerId] :*/ GameModeManager.ClientFrame;
ulong currentFrame = GameModeManager.ServerFrame;
for (; currentFrame <= maxFrame; currentFrame++)
{
if (!input.GetState(currentFrame, out var pastInputState, out var pastActorState))
{
//Console.Print($"not predicting");
//canpredict = false;
break;
}
}
ulong lastFrame = currentFrame;
if (input is PlayerInputNetwork)
{
//canpredict = true;
//lastFrame = GameModeManager.ServerFrame+1;
}
predicting = true;
currentFrame = GameModeManager.ServerFrame;
for (; currentFrame < lastFrame; currentFrame++)
{
if (!input.GetState(currentFrame, out var pastInputState, out var pastActorState))
{
Console.Print($"unexpected predict failure: {currentFrame}");
break;
}
if (currentFrame == inputState.frame)
jumped = jumped;
if (currentFrame == GameModeManager.ServerFrame)
{
Actor.Position = pastActorState.position;
currentVelocity = pastActorState.velocity;
lastJumped = pastActorState.lastJumpTime;
numJumps = pastActorState.numJumps;
jumped = pastActorState.jumped;
SetCameraEulerAngles(pastActorState.viewAngles, true);
if (Actor.Position.Length < 0.1)
jumped = jumped;
continue;
//rootActor.Orientation = pastActorState.orientation;
//viewAngles = pastActorState.viewAngles;
//viewAngles = new Float3(pastActorState.viewAngles.Y, pastActorState.viewAngles.X, pastActorState.viewAngles.Z);
}
else
ApplyInputToCamera(pastInputState, true);
//SetCameraEulerAngles(pastActorState.viewAngles, true);
//if (currentVelocity.Length > 0)
// currentVelocity = currentVelocity;
//else
// ApplyInputToCamera(pastInputState, true);
SimulatePlayerMovement(pastInputState);
break;
/*if ((Actor.Position - pastActorState.position).Length > 0.001)
Console.Print($"mispredicted position");
if ((currentVelocity - pastActorState.velocity).Length > 0.001)
Console.Print($"mispredicted velocity");
if ((viewAngles - pastActorState.viewAngles).Length > 0.001)
Console.Print($"mispredicted viewangles: {viewAngles - oldAngles}");*/
//Console.Print($"predicted: {currentFrame}");
}
/*if (input is PlayerInputNetwork)
{
currentFrame = lastFrame - 1;
if (input.GetState(currentFrame, out var lastInputState, out var lastActorState))
{
for (; currentFrame < GameModeManager.ClientFrame; currentFrame++)
{
ApplyInputToCamera(lastInputState, true);
SimulatePlayerMovement(lastInputState);
}
}
}*/
predicting = false;
}
else
{
//ApplyInputToCamera(inputState, true);
//SimulatePlayerMovement(inputState);
}
#endif
}
else
{
if (Actor.Position.Length < 0.1)
@@ -379,41 +484,59 @@ namespace Game
//viewAngles = viewAnglesLastFrame;
//ApplyInputToCamera(inputState);
var oldAngles = viewAngles;
//viewAngles = viewAnglesLastFrame;
bool canpredict = true;
if (true && input.Predict && GameModeManager.ClientFrame > 0 && GameModeManager.ServerFrame > 0)
{
for (ulong currentFrame = GameModeManager.ServerFrame; currentFrame < GameModeManager.ClientFrame; currentFrame++)
ulong currentFrame = GameModeManager.ServerFrame;
for (; currentFrame < GameModeManager.ClientFrame; currentFrame++)
{
if (!input.GetState(currentFrame, out var pastInputState, out var pastActorState))
{
Console.Print($"not predicting");
//Console.Print($"not predicting");
canpredict = false;
break;
}
}
ulong lastFrame = currentFrame;
if (canpredict)
{
//var oldPos = Actor.Position;
//var oldVel = currentVelocity;
{
var oldAngles = viewAngles;
var oldPos = Actor.Position;
var oldVel = currentVelocity;
predicting = true;
for (ulong currentFrame = GameModeManager.ServerFrame; currentFrame < GameModeManager.ClientFrame; currentFrame++)
currentFrame = GameModeManager.ServerFrame;
for (; currentFrame < lastFrame; currentFrame++)
{
if (!input.GetState(currentFrame, out var pastInputState, out var pastActorState))
{
Console.Print($"predict failure: {currentFrame}");
Console.Print($"unexpected predict failure: {currentFrame}");
break;
}
if (currentFrame == inputState.frame)
jumped = jumped;
if (currentFrame == GameModeManager.ServerFrame)
{
Actor.Position = pastActorState.position;
currentVelocity = pastActorState.velocity;
lastJumped = pastActorState.lastJumpTime;
numJumps = pastActorState.numJumps;
jumped = pastActorState.jumped;
SetCameraEulerAngles(pastActorState.viewAngles, true);
//cameraHolder.Orientation = Quaternion.Euler(pastActorState.viewAngles.Y, pastActorState.viewAngles.X, pastActorState.viewAngles.Z);
//ApplyInputToCamera(pastInputState, true);
//if (pastActorState.viewAngles != new Float3(90f, 0f, 0f))
// Console.Print($"moved server frame: {currentFrame}, {pastActorState.viewAngles}");
if (Actor.Position.Length < 0.1)
jumped = jumped;
@@ -434,35 +557,45 @@ namespace Game
// ApplyInputToCamera(pastInputState, true);
SimulatePlayerMovement(pastInputState);
if ((Actor.Position - pastActorState.position).Length > 0.001)
/*if ((Actor.Position - pastActorState.position).Length > 0.001)
Console.Print($"mispredicted position");
if ((currentVelocity - pastActorState.velocity).Length > 0.001)
Console.Print($"mispredicted velocity");
if ((viewAngles - pastActorState.viewAngles).Length > 0.001)
Console.Print($"mispredicted viewangles: {viewAngles - oldAngles}");
Console.Print($"mispredicted viewangles: {viewAngles - oldAngles}");*/
//Console.Print($"predicted: {currentFrame}");
}
predicting = false;
/*if ((Actor.Position - oldPos).Length > 0.001)
if ((Actor.Position - oldPos).Length > 0.001)
Console.Print($"mispredicted final position");
if ((currentVelocity - oldVel).Length > 0.001)
Console.Print($"mispredicted final velocity");*/
Console.Print($"mispredicted final velocity");
ApplyInputToCamera(inputState, true);
// Ensure orientation is always up-to-date after predicting
//rootActor.Orientation = Quaternion.Euler(0, viewAngles.X, 0);
cameraHolder.Orientation = Quaternion.Euler(viewAngles.Y, viewAngles.X, viewAngles.Z);
//if (input is not PlayerInputNetwork)
{
/*if ((Actor.Position - oldPos).Length > 0.001)
Console.Print($"mispredicted final position");
if ((currentVelocity - oldVel).Length > 0.001)
Console.Print($"mispredicted final velocity");*/
SimulatePlayerMovement(inputState);
ApplyInputToCamera(inputState, true);
// Ensure orientation is always up-to-date after predicting
//rootActor.Orientation = Quaternion.Euler(0, viewAngles.X, 0);
cameraHolder.Orientation = Quaternion.Euler(viewAngles.Y, viewAngles.X, viewAngles.Z);
SimulatePlayerMovement(inputState);
}
if ((viewAngles - oldAngles).Length > 0.001)
Console.Print($"mispredicted final viewangles: {viewAngles - oldAngles}");
Console.Print($"mispredicted final viewangles: {viewAngles} <- {oldAngles}");
//if (viewAngles != new Float3(90f, 0f, 0f))
// Console.Print($"moved client frame: {GameModeManager.ClientFrame}, {viewAngles}");
//Console.Print($"current: {inputState.frame}");
//if (GameModeManager.ClientFrame - GameModeManager.ServerFrame > 0)
@@ -474,7 +607,6 @@ namespace Game
if (!canpredict)
{
SetCameraEulerAngles(viewAnglesLastFrame, true);
ApplyInputToCamera(inputState, true);
SimulatePlayerMovement(inputState);
@@ -503,21 +635,30 @@ namespace Game
//SetCameraEulerAngles(new Float3(pastActorState.viewAngles.Y, pastActorState.viewAngles.X, pastActorState.viewAngles.Z), true);
//SetCameraEulerAngles(new Float3(viewAnglesLastFrame.Y, viewAnglesLastFrame.X, viewAnglesLastFrame.Z), true);
//SimulatePlayerMovement(inputState);
input.RecordCurrentActorState(new PlayerActorState
{
position = Actor.Position,
velocity = currentVelocity,
orientation = rootActor.Orientation,
viewAngles = viewAngles,
lastJumpTime = lastJumped,
numJumps = numJumps,
jumped = jumped,
//viewAngles = new Float3(viewAngles.Y, viewAngles.X, viewAngles.Z)
});
//Console.Print($"recording frame {input.frame}, client: {GameModeManager.ClientFrame}, server: {GameModeManager.ServerFrame}");
input.OnEndFrame();
}
if (Actor.Position.Length < 0.1)
jumped = jumped;
input.RecordCurrentActorState(new PlayerActorState
{
position = Actor.Position,
velocity = currentVelocity,
orientation = rootActor.Orientation,
viewAngles = viewAngles,
lastJumpTime = lastJumped,
//viewAngles = new Float3(viewAngles.Y, viewAngles.X, viewAngles.Z)
});
input.OnEndFrame();
if (input is PlayerInputNetwork)
jumped = jumped;
//lastInputFrame = currentInputFrame;
@@ -533,7 +674,7 @@ namespace Game
}*/
}
private void ApplyInputToCamera(PlayerInputState inputState, bool wrapAround = true)
public void ApplyInputToCamera(PlayerInputState inputState, bool wrapAround = true)
{
if (inputState.viewDeltaX == 0.0f && inputState.viewDeltaY == 0.0f)
return;
@@ -543,7 +684,7 @@ namespace Game
SetCameraEulerAngles(new Float3(viewYaw, viewPitch, viewAngles.Z), wrapAround);
}
private void SetCameraEulerAngles(Float3 angles, bool wrapAround = true)
public void SetCameraEulerAngles(Float3 angles, bool wrapAround = true)
{
if (viewAngles == angles)
return;
@@ -785,7 +926,40 @@ namespace Game
}
else if (boxCollider && boxCollider.IsActive)
{
DebugDraw.DrawWireBox(boxCollider.OrientedBox.GetBoundingBox(), Color.GreenYellow * 0.8f);
var clientBbox = boxCollider.OrientedBox.GetBoundingBox();
if (false)
{
if (GameModeManager.ServerFrame > 0 && GameModeManager.ClientFrame > 0)
for (ulong frame = GameModeManager.ServerFrame; frame < GameModeManager.ClientFrame; frame++)
{
if (!input.GetState(frame, out var pastInputState, out var pastActorState))
continue;
var bbox = clientBbox;
bbox.Center = pastActorState.position;
Float4 color1 = new Float4(Color.Red.R, Color.Red.G, Color.Red.B, Color.Red.A);
Float4 color2 = new Float4(Color.Blue.R, Color.Blue.G, Color.Blue.B, Color.Blue.A);
Float4 color3 = Float4.Lerp(color1, color2, (float)(frame - GameModeManager.ServerFrame) / (float)(GameModeManager.ClientFrame - GameModeManager.ServerFrame));
Color color = new Color(color3.X, color3.Y, color3.Z, color3.W);
DebugDraw.DrawBox(bbox, color * 1f);
}
}
else
{
var serverBbox = boxCollider.OrientedBox.GetBoundingBox();
if (input.GetState(GameModeManager.ServerFrame, out var serverInputState, out var serverActorState))
serverBbox.Center = serverActorState.position;
if (serverBbox.Center == clientBbox.Center)
DebugDraw.DrawBox(clientBbox, Color.Magenta * 0.6f);
else
{
DebugDraw.DrawBox(serverBbox, Color.Red * 0.6f);
DebugDraw.DrawBox(clientBbox, Color.Blue * 0.6f);
}
}
}
}
#endif
@@ -1051,6 +1225,7 @@ namespace Game
if (onGround && jumpAction && !jumped)
if (OnJump(traceGround, ref position, ref velocity))
{
//Console.Print($"{inputState.frame} jumped " + ", predicting: " + predicting + ", vel: " + velocity.Y);
jumped = true;
lastJumped = simulationTime;
numJumps++;