コード例 #1
0
ファイル: Player.cs プロジェクト: Earde/ShooterServer
    public void FixedUpdate()
    {
        //Is time synced?
        syncedTime.SendTimePacket(id);
        if (!syncedTime.isReady)
        {
            return;
        }
        //Initialize ticks
        if (ticks.Count == 0)
        {
            InitInputAndTicks();
        }
        //Get client time
        float currentTime = syncedTime.GetClientTime();
        //Clone multithreaded lists
        List <UserInput> tempUnprocessedUserInput = unprocessedUserInput.Clone();

        tempUnprocessedUserInput.RemoveAll(u => u.Time < ticks.First().Time || u.Time < currentTime - saveTime);
        unprocessedUserInput = new ThreadSafeList <UserInput>(tempUnprocessedUserInput);
        List <UserInput> uInput = unprocessedUserInput.Clone();

        //Is Alive
        if (health > 0f)
        {
            //Has new client input
            if (uInput.Count > 0)
            {
                Vector2 _inputDirection = Vector2.zero;
                uInput = uInput.OrderBy(x => x.Time).ToList();
                //Merge processed + unprocessed inputs
                List <UserInput> allInputs = new List <UserInput>();
                allInputs.AddRange(processedUserInput);
                allInputs.AddRange(uInput);

                //Server Reconciliation
                //Create new ticks
                if (uInput.First().Time < ticks.Last().Time)
                {
                    //Rewind ticks till oldest unprocessedUserInput
                    ticks.RemoveAll(t => t.Time > uInput.First().Time);
                    //Set last valid tick information
                    characterController.enabled            = false;
                    characterController.transform.position = ticks.Last().Position;
                    characterController.transform.rotation = ticks.Last().Rotation;
                    yVelocity = ticks.Last().YVelocity;
                    characterController.enabled = true;
                    characterController.Move(Vector3.zero); //Reset isGrounded
                    if (ticks.Count > 2)
                    {
                        animationController.RewindAnimation(ticks.Last().AnimationTime, ticks.Last().Position - ticks[ticks.Count - 2].Position, transform.forward);
                    }

                    float newTickTime;
                    do
                    {
                        float lastTickTime = ticks.Last().Time;
                        newTickTime = lastTickTime + Time.fixedDeltaTime;
                        if (newTickTime > currentTime)
                        {
                            newTickTime = currentTime;
                        }
                        List <UserInput> movesThisTick = allInputs.Where(a => a.Time > lastTickTime && a.Time <= newTickTime).OrderBy(ui => ui.Time).ToList();
                        UserInput        prevTickMove  = allInputs.Where(a => a.Time <= lastTickTime).OrderByDescending(x => x.Time).FirstOrDefault();
                        if (prevTickMove != default && prevTickMove != null)
                        {
                            prevTickMove.Time = ticks.Last().Time;
                            movesThisTick.Insert(0, prevTickMove);
                        }
                        if (movesThisTick.Count > 0)
                        {
                            //Apply tick inputs
                            for (int i = 0; i < movesThisTick.Count; i++)
                            {
                                float moveTime;
                                if (i == movesThisTick.Count - 1)
                                {
                                    moveTime = newTickTime - movesThisTick[i].Time;
                                }
                                else
                                {
                                    moveTime = movesThisTick[i + 1].Time - movesThisTick[i].Time;
                                }
                                Move(movesThisTick[i].Inputs, movesThisTick[i].Rotation, moveTime);
                            }
                        }
                        ticks.Add(new PlayerState {
                            Position = transform.position, Rotation = transform.rotation, Time = newTickTime, YVelocity = yVelocity, AnimationTime = animationController.GetNormalizedTime()
                        });
                    } while (newTickTime != currentTime);
                }
                //Create new tick
                else
                {
                    //Execute last ProcessedInput from last tick till first UnProcessedInput
                    float moveTime = uInput.First().Time - ticks.Last().Time;
                    Move(processedUserInput.Last().Inputs, processedUserInput.Last().Rotation, moveTime);
                    //Execute unprocessed Input
                    for (int i = 0; i < uInput.Count; i++)
                    {
                        if (i == uInput.Count - 1)
                        {
                            moveTime = currentTime - uInput[i].Time;
                        }
                        else
                        {
                            moveTime = uInput[i + 1].Time - uInput[i].Time;
                        }
                        Move(uInput[i].Inputs, uInput[i].Rotation, moveTime);
                    }
                    ticks.Add(new PlayerState {
                        Position = transform.position, Rotation = transform.rotation, Time = currentTime, YVelocity = yVelocity, AnimationTime = animationController.GetNormalizedTime()
                    });
                }
            }
            //No new unprocessed input
            //Execute last processed input
            //Create server tick
            else
            {
                Move(processedUserInput.Last().Inputs, processedUserInput.Last().Rotation, currentTime - ticks.Last().Time);
                ticks.Add(new PlayerState {
                    Position = transform.position, Rotation = transform.rotation, Time = currentTime, YVelocity = yVelocity, AnimationTime = animationController.GetNormalizedTime()
                });
            }
        }
        //Is Dead
        else
        {
            yVelocity = 0;
            ticks.Add(new PlayerState {
                Position = transform.position, Rotation = transform.rotation, Time = currentTime, YVelocity = yVelocity, AnimationTime = animationController.GetNormalizedTime()
            });
        }

        //move from unprocessed to processed
        foreach (UserInput u in uInput)
        {
            unprocessedUserInput.Remove(u);
            processedUserInput.Add(u);
        }
        //remove old input/ticks
        if (ticks.Count > saveTime / Time.fixedDeltaTime)
        {
            ticks.RemoveAt(0);
        }
        while (processedUserInput.Count > saveTime / Time.fixedDeltaTime)
        {
            processedUserInput.RemoveAt(0);
        }
        processedUserInput = processedUserInput.OrderBy(pui => pui.Time).ToList();
        //send new tick to all players
        ServerSend.PlayerData(id, ticks.Last(), (int)score.damageDone, score.kills, score.deaths);

        Logs();
    }