Пример #1
0
        public void CreatePlayer(byte actorId, ushort type)
        {
            var bornPos   = _gameConstStateService.PlayerBornPoss[actorId % _gameConstStateService.PlayerBornPoss.Count];
            var createPos = bornPos + _gameConfigService.TankBornOffset;

            _gameEffectService.ShowBornEffect(createPos);
            _gameAudioService.PlayClipBorn();
            EDir dir = EDir.Up;

            DelayCall(_gameConfigService.TankBornDelay, () => {
                var entity       = CreateUnit(createPos, EntityUtil.CreateEntityPlayer(_gameContext, type), dir);
                entity.unit.camp = ECampType.Player;
                var actor        = _actorContext.GetEntityWithActorId(actorId);
                if (actor != null)
                {
                    actor.ReplaceGameEntityId(entity.entityId.value);
                    entity.ReplaceActorId(actorId);
                }
                else
                {
                    Debug.LogError(
                        $"can not find a actor after create a game player actorId:{actorId} entityId{entity.entityId.value}");
                }
            });
        }
        protected override void DoRollbackTo(int tick, int missFrameTick, bool isNeedClear = true)
        {
            var snapshotIndices = _snapshotContext.GetEntities(SnapshotMatcher.Tick)
                                  .Where(entity => entity.tick.value <= tick).Select(entity => entity.tick.value).ToList();

            if (snapshotIndices.Count <= 0)
            {
                return;
            }
            snapshotIndices.Sort();
            Logging.Debug.Assert(snapshotIndices.Count > 0 && snapshotIndices[0] <= tick,
                                 $"Error! no correct history frame to revert minTick{(snapshotIndices.Count > 0 ? snapshotIndices[0] : 0)} targetTick {tick}");
            int i = snapshotIndices.Count - 1;

            for (; i >= 0; i--)
            {
                if (snapshotIndices[i] <= tick)
                {
                    break;
                }
            }

            var resultTick = snapshotIndices[i];

            if (resultTick == Tick)
            {
                Logging.Debug.Log("SelfTick should not rollback");
                return;
            }

            var snaps = "";

            foreach (var idx in snapshotIndices)
            {
                snaps += idx + " ";
            }

            Logging.Debug.Log(
                $"Rolling back {Tick}->{tick} :final from {resultTick} to {_gameStateContext.tick.value}  " +
                $"missTick:{missFrameTick} total:{Tick - resultTick} ");

            /*
             * ====================== Revert actors ======================
             * most importantly: the entity-count per actor gets reverted so the composite key (Id + ActorId) of GameEntities stays in sync
             */

            var backedUpActors =
                _actorContext.GetEntities(ActorMatcher.Backup).Where(e => e.backup.tick == resultTick);

            foreach (var backedUpActor in backedUpActors)
            {
                var target = _actorContext.GetEntityWithActorId(backedUpActor.backup.actorId);
                if (target == null)
                {
                    target = _actorContext.CreateEntity();
                    target.AddActorId(backedUpActor.backup.actorId);
                }

                //CopyTo does NOT remove additional existing components, so remove them first
                var additionalComponentIndices = target.GetComponentIndices().Except(
                    backedUpActor.GetComponentIndices()
                    .Except(new[] { ActorComponentsLookup.Backup })
                    .Concat(new[] { ActorComponentsLookup.ActorId }));

                foreach (var index in additionalComponentIndices)
                {
                    target.RemoveComponent(index);
                }

                backedUpActor.CopyTo(target, true,
                                     backedUpActor.GetComponentIndices().Except(new[] { ActorComponentsLookup.Backup }).ToArray());
            }

            /*
             * ====================== Revert game-entities ======================
             */
            var currentEntities = _gameContext.GetEntities(GameMatcher.EntityId);
            var backupEntities  = _gameContext.GetEntities(GameMatcher.Backup).Where(e => e.backup.tick == resultTick)
                                  .ToList();
            var backupEntityIds = backupEntities.Select(entity => entity.backup.entityId);

            //Entities that were created in the prediction have to be destroyed
            var invalidEntities = currentEntities.Where(entity => !backupEntityIds.Contains(entity.entityId.value))
                                  .ToList();

            foreach (var invalidEntity in invalidEntities)
            {
                invalidEntity.isDestroyed = true;
            }


            //Copy old state to the entity
            foreach (var backupEntity in backupEntities)
            {
                var target = _gameContext.GetEntityWithEntityId(backupEntity.backup.entityId);
                if (target == null)
                {
                    target = _gameContext.CreateEntity();
                    target.AddEntityId(backupEntity.backup.entityId);
                }

                //CopyTo does NOT remove additional existing components, so remove them first
                var additionalComponentIndices = target.GetComponentIndices().Except(
                    backupEntity.GetComponentIndices()
                    .Except(new[] { GameComponentsLookup.Backup })
                    .Concat(new[] { GameComponentsLookup.EntityId }));

                foreach (var index in additionalComponentIndices)
                {
                    target.RemoveComponent(index);
                }

                backupEntity.CopyTo(target, true,
                                    backupEntity.GetComponentIndices().Except(new[] { GameComponentsLookup.Backup }).ToArray());
            }

            //将太后 和太前的snapshot 删除掉
            if (isNeedClear)
            {
                foreach (var invalidBackupEntity in _actorContext.GetEntities(ActorMatcher.Backup)
                         .Where(e => e.backup.tick != resultTick))
                {
                    invalidBackupEntity.Destroy();
                }

                foreach (var invalidBackupEntity in _gameContext.GetEntities(GameMatcher.Backup)
                         .Where(e => e.backup.tick != resultTick))
                {
                    invalidBackupEntity.Destroy();
                }

                foreach (var snapshotEntity in _snapshotContext.GetEntities(SnapshotMatcher.Tick)
                         .Where(e => e.tick.value != resultTick))
                {
                    snapshotEntity.Destroy();
                }
            }

            //TODO: restore locally destroyed entities

            //Cleanup game-entities that are marked as destroyed
            _systems.Cleanup();
            _gameStateContext.ReplaceTick(resultTick);
            _timeMachineService.RollbackTo(resultTick);
        }