コード例 #1
0
 private void CheckAndRideOnVehicle(PlayerEntity playerEntity, int vehicleEntityId, int seatId)
 {
     if (CheckRideOnVehicle(playerEntity))
     {
         var vehicle = _vehicleContext.GetEntityWithEntityKey(new EntityKey(vehicleEntityId, (short)EEntityType.Vehicle));
         if (DistanceTooLarge(playerEntity, vehicle))
         {
             Logger.Error("player is too far away from vehicle , wrong logic or client is cheating");
             return;
         }
         if (vehicle != null)
         {
             var preferedSeat = seatId;
             if (!vehicle.vehicleSeat.IsOccupied(seatId))
             {
                 playerEntity.autoMoveInterface.PlayerAutoMove.StopAutoMove();
                 RideOnVehicle(playerEntity, vehicle, preferedSeat);
             }
             else
             {
                 var seat = vehicle.FindPreferedSeat(playerEntity);
                 RideOnVehicle(playerEntity, vehicle, seat);
                 Logger.Error("seat client use is occupied, wrong logic or client is cheating ");
             }
         }
         else
         {
             Logger.ErrorFormat("no vehicle entity with id {0}", vehicleEntityId);
         }
     }
 }
コード例 #2
0
        public HitBoxComponent GetHitBoxComponent(EntityKey entityKey)
        {
            var entity = _vehicleContext.GetEntityWithEntityKey(entityKey);

            if (entity != null && entity.hasPosition && entity.hasHitBox)
            {
                return(entity.hitBox);
            }

            return(null);
        }
コード例 #3
0
        public static void SetCharacterStateWithVehicle(this PlayerEntity playerEntity, Contexts contexts, VehicleContext context)
        {
            if (playerEntity.hasCharacterContoller)
            {
                bool enabled    = !playerEntity.IsOnVehicle();
                var  controller = playerEntity.characterContoller.Value;

                if (controller.enabled != enabled)
                {
                    bool success = SetCharacterPositionOnVehicle(playerEntity, context);

                    if (success)
                    {
                        if (enabled && playerEntity.gamePlay.IsLifeState(EPlayerLifeState.Dead))
                        {
                            controller.enabled = false;
                        }
                        else
                        {
                            controller.enabled = enabled;
                        }

                        if (playerEntity.hasStateInterface)
                        {
                            bool isStateDrive = playerEntity.stateInterface.State.GetActionKeepState() ==
                                                XmlConfig.ActionKeepInConfig.Drive;
                            if (!enabled && !isStateDrive)
                            {
                                var vehicle = context.GetEntityWithEntityKey(playerEntity.controlledVehicle.EntityKey);
                                playerEntity.DriveStart(contexts, playerEntity.controlledVehicle.Role, vehicle.vehicleAssetInfo.PostureId);
                            }
                            else if (enabled && isStateDrive)
                            {
                                playerEntity.stateInterface.State.DriveEnd();
                            }
                        }

                        // 上车并且是主驾驶位,设置IK
                        if (playerEntity.IsVehicleDriver())
                        {
                            var vehicle = context.GetEntityWithEntityKey(playerEntity.controlledVehicle.EntityKey);
                            playerEntity.SetSteeringWheelIK(vehicle);
                        }
                        else
                        {
                            playerEntity.EndSteeringWheelIK();
                        }
                    }
                }
            }
        }
コード例 #4
0
        public void ExecuteUserCmd(IPlayerUserCmdGetter getter, IUserCmd cmd)
        {
            var playerEntity = (PlayerEntity)getter.OwnerEntity;

            if (playerEntity.IsOnVehicle())
            {
                var channel = cmd.ChangeChannel;
                if (channel > 0 && playerEntity.IsVehicleDriver())
                {
                    var vehicle = _context.GetEntityWithEntityKey(playerEntity.controlledVehicle.EntityKey);
                    if (vehicle != null)
                    {
                        var assetInfo = vehicle.vehicleAssetInfo;
                        if (assetInfo.HasRadio)
                        {
                            var gameData = vehicle.GetGameData();
                            if (gameData.SoundChannel != channel)
                            {
                                gameData.SetSoundChannel((EVehicleChannel)channel);
                            }
                            else
                            {
                                gameData.SetSoundChannel(EVehicleChannel.None);
                            }

                            _logger.DebugFormat("Change Vehicle {0} Sound Channel {1} Music Sound Id {2}",
                                                vehicle.entityKey.Value, gameData.SoundChannel, gameData.CurrentSoundId);
                        }
                    }
                }
            }
        }
コード例 #5
0
        private static VehicleEntity GetVehicleByHierachy(PlayerEntity player, VehicleContext context)
        {
            VehicleEntity vehicle = null;

            if (player.IsOnVehicle())
            {
                var controlledEntity = player.controlledVehicle;
                vehicle = context.GetEntityWithEntityKey(controlledEntity.EntityKey);
            }
            else
            {
                var transform = player.RootGo().transform.parent;
                while (transform != null)
                {
                    if (transform.GetComponent <VehicleCommonController>() != null)
                    {
                        var reference = transform.GetComponent <EntityReference>();
                        if (reference != null)
                        {
                            vehicle = (VehicleEntity)reference.Reference;
                        }
                        break;
                    }

                    transform = transform.parent;
                }
            }

            return(vehicle);
        }
コード例 #6
0
        protected override void SetActive(ActiveSetting activeSetting)
        {
            var vehicle = activeSetting.Vehicle;
            var active  = activeSetting.Active;

            vehicle.SetActive(active);
            if (active)
            {
                if (_isPredictMode)
                {
                    NotifyVehicleActive(vehicle);
                }
                else
                {
                    var selfEntity = PlayerContext.flagSelfEntity;

                    if (selfEntity.IsOnVehicle() &&
                        vehicle == VehicleContext.GetEntityWithEntityKey(selfEntity.controlledVehicle.EntityKey))
                    {
                        NotifyVehicleActive(vehicle);
                    }
                }

                vehicle.SetLodLevel(activeSetting.LowLod);
            }
        }
コード例 #7
0
        public static IVehicleCmd CreateVehicleCmd(IVehicleCmdGenerator generator, VehicleContext context, PlayerEntity player, int currentSimulationTime)
        {
            if (!player.IsOnVehicle())
            {
                return(null);
            }

            var vehicle = context.GetEntityWithEntityKey(player.controlledVehicle.EntityKey);

            if (vehicle == null)
            {
                return(null);
            }


            var vehicleCmd = generator.GeneratorVehicleCmd(currentSimulationTime);

            if (vehicleCmd == null)
            {
                return(null);
            }

            vehicleCmd.PlayerId  = player.entityKey.Value.EntityId;
            vehicleCmd.VehicleId = vehicle.entityKey.Value.EntityId;

            if (!SharedConfig.ServerAuthorative)
            {
                vehicle.SetVehicleStateToCmd(vehicleCmd);
            }

            return(vehicleCmd);
        }
コード例 #8
0
        private static VehicleEntity GetVehicle(VehicleContext context, int id)
        {
            if (SharedConfig.IsOffline)
            {
                id += EntityIdGenerator.LocalBaseId;
            }

            var entityKey = new EntityKey(id, (short)EEntityType.Vehicle);

            return(context.GetEntityWithEntityKey(entityKey));
        }
コード例 #9
0
        protected override void DoSetData(PointerData data)
        {
            _seatId    = 0;
            _vehicleId = VehicleCastData.EntityId(data.IdList);
            var vehicleEntity = _vehicleContext.GetEntityWithEntityKey(new Core.EntityComponent.EntityKey(_vehicleId, (short)EEntityType.Vehicle));

            if (null != vehicleEntity)
            {
                if (vehicleEntity.hasPosition)
                {
                    var player = _playerContext.flagSelfEntity;
                    if (player.hasPosition)
                    {
                        var dis = Vector3.Distance(vehicleEntity.position.Value, player.position.Value);
                        if (IsUntouchableOffGround(player, data.Position, vehicleEntity.gameObject.UnityObject))
                        {
                            return;
                        }
                        if (!player.IsOnVehicle())
                        {
                            if (!player.IsVehicleEnterable(vehicleEntity) ||
                                !vehicleEntity.IsFocusable())
                            {
                                return;
                            }

                            if (!vehicleEntity.IsRidable())
                            {
                                Tip = string.Format(ScriptLocalization.client_actiontip.pullupvehicle, vehicleEntity.vehicleAssetInfo.TipName);
                                return;
                            }


                            var hitPos = data.Position;
                            _seatId = vehicleEntity.FindPreferedSeat(hitPos);
                            if (_seatId == (int)VehicleSeatIndex.None)
                            {
                                return;
                            }
                            if (_seatId == (int)VehicleSeatIndex.Driver)
                            {
                                Tip = string.Format(ScriptLocalization.client_actiontip.drivevehicle, vehicleEntity.vehicleAssetInfo.TipName);
                            }
                            else
                            {
                                Tip = string.Format(ScriptLocalization.client_actiontip.entervehicle, vehicleEntity.vehicleAssetInfo.TipName);
                            }
                        }
                    }
                }
            }
        }
コード例 #10
0
 public static Transform GetVehicleSeatTransform(this PlayerEntity player, VehicleContext context)
 {
     if (player.IsOnVehicle())
     {
         var controlledEntity = player.controlledVehicle;
         var vehicle          = context.GetEntityWithEntityKey(controlledEntity.EntityKey);
         if (vehicle != null)
         {
             return(vehicle.GetVehicleSeatTransform(player));
         }
     }
     return(null);
 }
コード例 #11
0
        public DrivePoseMotor(ECameraPoseMode modeId,
                              HashSet <ECameraPoseMode> excludes,
                              VehicleContext vehicleContext,
                              FreeMoveContext freeMoveContext,
                              Motors m
                              ) : base(m)
        {
            _modeId = (short)modeId;
            _motors = m;

            this.excludes = new HashSet <short>();
            foreach (var e in excludes)
            {
                this.excludes.Add((short)e);
            }

            _order = SingletonManager.Get <CameraConfigManager>().GetRoleConfig()
                     .GetCameraConfigItem((ECameraPoseMode)_modeId).Order;

            _motors.ActionManager.AddAction(CameraActionType.Enter, SubCameraMotorType.Pose, (int)modeId,
                                            (player, state) =>
            {
                if (player.IsOnVehicle())
                {
                    var vehicle = vehicleContext.GetEntityWithEntityKey(player.controlledVehicle.EntityKey);
                    player.controlledVehicle.CameraAnchorOffset    = vehicle.vehicleAssetInfo.CameraAnchorOffset;
                    player.controlledVehicle.CameraDistance        = vehicle.vehicleAssetInfo.CameraDistance;
                    player.controlledVehicle.CameraRotationDamping = vehicle.vehicleAssetInfo.CameraRotationDamping;
                }

                var cameraEulerAngle = player.cameraFinalOutputNew.EulerAngle;

                var carEulerAngle = player.cameraArchor.ArchorEulerAngle;

                var t           = cameraEulerAngle - carEulerAngle;
                state.FreeYaw   = t.y;
                state.FreePitch = t.x;
            });
            _motors.ActionManager.AddAction(CameraActionType.Leave, SubCameraMotorType.Pose, (int)modeId,
                                            (player, state) =>
            {
                var rotation             = player.cameraFinalOutputNew.EulerAngle;
                player.orientation.Yaw   = YawPitchUtility.Normalize(rotation.y);
                player.orientation.Pitch = YawPitchUtility.Normalize(rotation.x);

                state.LastFreePitch = 0;
                state.LastFreeYaw   = 0;
                state.FreeYaw       = 0f;
                state.FreePitch     = 0f;
            });
        }
コード例 #12
0
    public static VehicleEntity GetVehicle(PlayerEntity player, VehicleContext context)
    {
        if (null != player && player.IsOnVehicle())
        {
            var controlledComp = player.controlledVehicle;
            var vehicleEntity  = context.GetEntityWithEntityKey(controlledComp.EntityKey);

            if (vehicleEntity != null)
            {
                return(vehicleEntity);
            }
        }
        return(null);
    }
コード例 #13
0
        public Vector3 GetPosition(EntityKey entityKey)
        {
            var entity = _vehicleContext.GetEntityWithEntityKey(entityKey);

            if (entity != null && entity.hasPosition && entity.hasHitBox)
            {
                return(entity.hitBox.HitPreliminaryGeo.position);
            }
            return(Vector3.zero);
        }
コード例 #14
0
    public static VehicleEntity GetControlledVehicle(PlayerEntity player, VehicleContext context)
    {
        var selfPlayer = player;

        if (selfPlayer != null && selfPlayer.IsOnVehicle())
        {
            var controlledComp = selfPlayer.controlledVehicle;
            var vehicleEntity  = context.GetEntityWithEntityKey(controlledComp.EntityKey);

            if (vehicleEntity != null && player.IsVehicleDriver())
            {
                return(vehicleEntity);
            }
        }
        return(null);
    }
コード例 #15
0
        private void ProcessCollisionDamages(Dictionary <EntityKey, VehicleCollisionDamage> damageToVehicles)
        {
            if ((SharedConfig.IsServer && !SharedConfig.DynamicPrediction))
            {
                return;
            }

            foreach (var pair in damageToVehicles)
            {
                var vehicle = _vehicleContext.GetEntityWithEntityKey(pair.Key);

                if (vehicle != null)
                {
                    bool sendToServer = false;
                    if (SharedConfig.CalcVehicleCollisionDamageOnClient)
                    {
                        if (SharedConfig.IsServer)
                        {
                            //the collision damage for server-side vehicle with driver is calculated on client-side of driver player.
                            if (vehicle.HasDriver())
                            {
                                continue;
                            }
                        }
                        else
                        {
                            if (!SharedConfig.IsOffline && SharedConfig.DynamicPrediction)
                            {
                                var selfEntity = _playerContext.flagSelfEntity;
                                //the collision damage for client-side vehicle with not-self driver is calculated on server-side.
                                if (!vehicle.IsVehicleDriver(selfEntity))
                                {
                                    continue;
                                }
                            }

                            sendToServer = true;
                        }
                    }

                    DoCollisionDamageToVehicle(vehicle, pair.Value.AverageVehicleDamage, sendToServer);
                    DoCollisionDamageToPassagers(vehicle, pair.Value.AveragePassagerDamage, sendToServer);
                }
            }

            damageToVehicles.Clear();;
        }
コード例 #16
0
        public void ExecuteUserCmd(IPlayerUserCmdGetter getter, IUserCmd cmd)
        {
            var playerEntities = _playerContext.GetEntities();
            var ownerEntity    = getter.OwnerEntity as PlayerEntity;

            for (var i = 0; i < playerEntities.Length; ++i)
            {
                var playerEntity = playerEntities[i];
                if (!playerEntity.IsOnVehicle())
                {
                    continue;
                }

                var seat = playerEntity.GetVehicleSeatTransform(_vehicleContext);
                if (null == seat)
                {
                    continue;
                }
                var characterTransform = playerEntity.RootGo().transform;
                var character          = playerEntity.RootGo();
                if (seat != characterTransform.parent)
                {
                    _mount.MountCharacterToVehicleSeat(character, seat);

                    // 切换座位,并且换到主驾驶位,设置IK
                    if (playerEntity.IsVehicleDriver())
                    {
                        var vehicle = _vehicleContext.GetEntityWithEntityKey(playerEntity.controlledVehicle.EntityKey);
                        playerEntity.SetSteeringWheelIK(vehicle);
                    }
                    else
                    {
                        playerEntity.EndSteeringWheelIK();
                    }
                }

                if (ownerEntity == playerEntity)
                {
                    playerEntity.position.Value  = characterTransform.position;
                    playerEntity.orientation.Yaw = characterTransform.rotation.eulerAngles.y;
                }
            }
        }
コード例 #17
0
        public void ExecuteUserCmd(IUserCmdOwner owner, IUserCmd cmd)
        {
            var playerEntities = _playerContext.GetEntities();
            var ownerEntity    = owner.OwnerEntity as PlayerEntity;

            for (int i = 0; i < playerEntities.Length; ++i)
            {
                var playerEntity = playerEntities[i];
                if (!playerEntity.IsOnVehicle())
                {
                    continue;
                }

                Transform seat = playerEntity.GetVehicleSeatTransform(_vehicleContext);
                if (null == seat)
                {
                    continue;
                }
                var characterTransform = playerEntity.RootGo().transform;
                if (seat != characterTransform.parent)
                {
                    characterTransform.parent        = seat;
                    characterTransform.localPosition = Vector3.zero;
                    characterTransform.localRotation = Quaternion.identity;
                    // 切换座位,并且换到主驾驶位,设置IK
                    if (playerEntity.IsVehicleDriver())
                    {
                        var vehicle = _vehicleContext.GetEntityWithEntityKey(playerEntity.controlledVehicle.EntityKey);
                        playerEntity.SetSteeringWheelIK(vehicle);
                    }
                    else
                    {
                        playerEntity.EndSteeringWheelIK();
                    }
                }

                if (ownerEntity == playerEntity)
                {
                    playerEntity.position.Value  = characterTransform.position;
                    playerEntity.orientation.Yaw = characterTransform.rotation.eulerAngles.y;
                }
            }
        }
コード例 #18
0
        public void OnGamePlay()
        {
            var selfPlayer = _playerContext.flagSelfEntity;

            if (selfPlayer.IsOnVehicle())
            {
                var controlledVehicle = selfPlayer.controlledVehicle;
                if (selfPlayer.IsOnVehicle())
                {
                    var vehicle = _vehicleContext.GetEntityWithEntityKey(selfPlayer.controlledVehicle.EntityKey);
                    if (vehicle != null && vehicle.HasGameData())
                    {
                        var gameData = vehicle.GetGameData();

                        if (controlledVehicle.CurrentSoundId != gameData.CurrentSoundId)
                        {
                            if (_soundManager.Play(gameData.CurrentSoundId, gameData.SoundSyncTime))
                            {
                                _logger.DebugFormat("Change Music Sound From {0} to {1}",
                                                    controlledVehicle.CurrentSoundId, gameData.CurrentSoundId);

                                controlledVehicle.CurrentSoundId = gameData.CurrentSoundId;
                            }
                            else
                            {
                                controlledVehicle.CurrentSoundId = (int)EVehicleSoundId.WaitingForPlay;
                            }
                        }
                    }
                }
                else
                {
                    _soundManager.StopSound();
                    controlledVehicle.CurrentSoundId = (int)EVehicleSoundId.Invalid;
                }
            }
        }
コード例 #19
0
        public void ExecuteUserCmd(IUserCmdOwner owner, IUserCmd cmd)
        {
            var player = (PlayerEntity)owner.OwnerEntity;

            if (!player.IsOnVehicle() || !player.hasCameraConfigNow)
            {
                _newVehicle = true;
                return;
            }

            if (_newVehicle)
            {
                _lastTime   = Time.time;
                _newVehicle = false;
                return;
            }

            var currentTime = Time.time;

            var controlledVehicle = player.controlledVehicle;
            var vehicleEntity     = _vehicleContext.GetEntityWithEntityKey(controlledVehicle.EntityKey);

            if (vehicleEntity == null)
            {
                _lastTime = currentTime;
                return;
            }
            var target       = vehicleEntity.gameObject.UnityObjWrapper.Value.transform;
            var targetOffset = target.TransformDirection(controlledVehicle.CameraLocalTargetOffSet);

            var right = target.right;

            right.y = 0.0f;

            if (right.sqrMagnitude > 1e-4f)
            {
                right = right.normalized;

                var         forward       = Vector3.Cross(right, Vector3.up);
                const float radius        = 0.5f;
                var         localPosition = forward * radius;

                var localLastPosition = controlledVehicle.CameraLastPosition;

                if (Vector3.Dot(localLastPosition, localPosition) < 0)
                {
                    localPosition = -localPosition;
                }

                var deltaTime    = currentTime - _lastTime;
                var wantedAngle  = Mathf.Atan2(localPosition.x, localPosition.z) * Mathf.Rad2Deg;
                var currentAngle = Mathf.LerpAngle(controlledVehicle.CameraLastAngle, wantedAngle, deltaTime * controlledVehicle.CameraRotationDamping);

#if UNITY_EDITOR
                if (Mathf.Abs(currentAngle - controlledVehicle.CameraLastAngle) > 3.0f)
                {
                    Debug.LogFormat("Time delta {0} is too large, vehicle camera rotation angle from {1} to {2}, wanted angle {3}",
                                    deltaTime, controlledVehicle.CameraLastAngle, currentAngle, wantedAngle);
                }
#endif

                var center = target.position + targetOffset;
                controlledVehicle.CameraCurrentPosition = center;
                controlledVehicle.CameraCurrentRotation = Quaternion.Euler(0.0f, currentAngle, 0.0f);

                controlledVehicle.CameraLastPosition = localPosition;
                controlledVehicle.CameraLastAngle    = currentAngle;
            }

            _lastTime = currentTime;
        }
コード例 #20
0
        protected override void UpdateVehicles()
        {
            //enable/disable the gameobject according to distance
            var selfEntity          = PlayerContext.flagSelfEntity;
            var vehicleEntities     = Vehicles.GetEntities();
            var vehicleCount        = vehicleEntities.Length;
            var lodCullDistance     = _sqrLodDistance;
            var physicsCullDistance = SqrPhysicsDistance;

            if (SharedConfig.DisableVehicleCull)
            {
                lodCullDistance = physicsCullDistance = float.MaxValue;
            }

            for (int i = 0; i < vehicleCount; ++i)
            {
                var vehicle  = vehicleEntities[i];
                var distance = SqrDistance(selfEntity, vehicle);

                var active = false;
                var lowLod = true;
                if (distance < lodCullDistance * LodDistanceDamper)
                {
                    active = true;
                    if (distance < physicsCullDistance * PhysicsDistanceDamper)
                    {
                        lowLod = false;
                    }
                    else if (distance < physicsCullDistance)
                    {
                        lowLod = vehicle.IsLowLod();
                    }
                }
                else if (distance < lodCullDistance)
                {
                    active = vehicle.IsActiveSelf();
                    lowLod = vehicle.IsLowLod();
                }

                vehicle.SetActive(active);
                if (active)
                {
                    if (_isPredictMode)
                    {
                        NotifyVehicleActive(vehicle);
                    }
                    vehicle.SetLodLevel(lowLod);
                }
            }

            if (!_isPredictMode)
            {
                if (selfEntity.IsOnVehicle())
                {
                    var vehicle =
                        VehicleContext.GetEntityWithEntityKey(selfEntity.controlledVehicle.EntityKey);

                    if (vehicle != null)
                    {
                        NotifyVehicleActive(vehicle);
                    }
                }
            }
        }
コード例 #21
0
 public static VehicleEntity GetVehicleEntity(VehicleContext context, ControlledVehicleComponent vehicleComp)
 {
     return(context.GetEntityWithEntityKey(vehicleComp.EntityKey));
 }
コード例 #22
0
 private VehicleEntity GetCurrentVehicle()
 {
     return(_vehicleContext.GetEntityWithEntityKey(_playerContext.flagSelfEntity.controlledVehicle.EntityKey));
 }
コード例 #23
0
 private VehicleEntity GetCurrentVehicle()
 {
     return(_vehicleContext.GetEntityWithEntityKey(Player.controlledVehicle.EntityKey));
 }
コード例 #24
0
        private static void ResolveOverlapWithVehicle(VehicleContext context, PlayerEntity player, ICharacterControllerContext controller, float deltaTime)
        {
            var gamePlay = player.gamePlay;

            if (gamePlay.IsLifeState(EPlayerLifeState.Alive) && !gamePlay.IsVehicleCollisionState(EVehicleCollisionState.None))
            {
                var vehicle = context.GetEntityWithEntityKey(gamePlay.CollidedVehicleKey);
                if (vehicle != null && vehicle.hasGameObject)
                {
                    var transform = vehicle.gameObject.UnityObjWrapper.Value.transform;
                    var forward   = transform.forward;
                    var right     = transform.right;

                    var rootTransform   = player.characterContoller.Value.transform;
                    var playerPosition  = rootTransform.position;
                    var vehiclePosition = vehicle.gameObject.UnityObjWrapper.Value.transform.position;
                    var deltaPosition   = playerPosition - vehiclePosition;
                    deltaPosition.y = 0;
                    deltaPosition   = deltaPosition.normalized;
                    if (deltaPosition.sqrMagnitude < 1E-4f)
                    {
                        if (Mathf.Abs(forward.y) > 0.8)
                        {
                            deltaPosition = right;
                        }
                        else
                        {
                            deltaPosition = forward;
                        }
                    }

                    var moveDirection = Mathf.Abs(forward.y) < 0.8 ? forward : right;
                    var baseDirection = moveDirection;
                    var maxDot        = float.NegativeInfinity;

                    //select the best overlap-resolve direction
                    foreach (var angle in _resolveRotateAngle)
                    {
                        var direction = Quaternion.AngleAxis(angle, transform.up) * baseDirection;
                        var dot       = Vector3.Dot(direction, deltaPosition);
                        if (dot > maxDot)
                        {
                            moveDirection = direction;
                            maxDot        = dot;
                        }
                    }

                    //resolve overlap according to direction
                    const int maxIterator = 2;

                    var velcoity         = vehicle.GetLinearVelocity().magnitude;
                    var expectedDistance = velcoity * 0.333f;
                    for (int i = 1; i <= maxIterator; ++i)
                    {
                        moveDirection.y = 0;
                        moveDirection   = moveDirection.normalized;
                        //move forward to resolve overlap
                        float resolveDist = 5.5f * i /*+ 0.1f*/;
                        controller.Move(moveDirection * resolveDist, deltaTime);

                        var position = rootTransform.position;
                        if (VehicleEntityUtility.IsPlayerOverlapAtPosition(player, position, UnityLayers.VehicleLayerMask))
                        {
                            rootTransform.position = playerPosition;
                            continue;
                        }
                        //move backward to close vehicle
                        var backDist = (playerPosition - rootTransform.position);
//                        var backMag = backDist.magnitude;
//                        if (backMag > expectedDistance)
//                        {
//                            var backNorm = backDist.normalized;
//                            backMag = backMag - expectedDistance;
//                            backDist = backMag * backNorm;
//                        }

                        if (backDist.sqrMagnitude > 1E-4f)
                        {
                            controller.Move(backDist, deltaTime);
                        }

                        break;
                    }
                }
                gamePlay.CollidedVehicleKey = new EntityKey();
            }
        }