Exemplo n.º 1
0
 private void RotBox(PlayerEntity player, float deltaTime, PostureInConfig postureInConfig,
                     ICharacterControllerContext controller)
 {
     //旋转包围盒
     controller.SetCurrentControllerType(postureInConfig);
     controller.SetCharacterPosition(player.position.Value);
     controller.SetCharacterRotation(player.orientation.ModelView);
     controller.Rotate(player.orientation.RotationYaw, deltaTime);
 }
Exemplo n.º 2
0
 public static void Move(Contexts contexts, PlayerEntity player, ICharacterControllerContext controller, Vector3 dist, float deltaTime)
 {
     ResolveOverlapWithVehicle(contexts.vehicle, player, controller, deltaTime);
     // enlarge distance if movement too small
     if (dist.sqrMagnitude < 1E-4)
     {
         dist  = Vector3.Normalize(dist);
         dist *= 0.01f;
     }
     controller.Move(dist, deltaTime);
 }
Exemplo n.º 3
0
        private void JumpSpeedProject(ref Vector4 velocity, ICharacterControllerContext controller)
        {
            var surfaceNormal = controller.GetLastGroundNormal();
            var tmpVec        = new Vector3(velocity.x, 0, velocity.z);
            var newVelocity   = GetDirectionTangentToSurfaceCustom(tmpVec, surfaceNormal, controller.transform.forward) * tmpVec.magnitude;

            //_logger.InfoFormat("before:{2}, after transform:{0}, project:{1}", newVelocity.ToStringExt(), Vector3.ProjectOnPlane(newVelocity, Vector3.up), velocity);
            newVelocity = Vector3.ProjectOnPlane(newVelocity, Vector3.up);
//            DebugDraw.EditorDrawArrow(controller.GetLastGroundHitPoint(),
//                new Vector3(velocity.x, 0, velocity.z).normalized, new Color(0.4f, 0.9f, 1f), 3f);
//            DebugDraw.EditorDrawArrow(controller.GetLastGroundHitPoint(),
//                new Vector3(newVelocity.x, 0, newVelocity.z).normalized * 2f, new Color(1f, 0.2f, 1f), 3f);
            //_logger.InfoFormat("prev:{0}, after:{1}, surfaceNormal:{2}", velocity.ToStringExt(),newVelocity.ToStringExt(), surfaceNormal.ToStringExt());

            velocity.x = newVelocity.x;
            velocity.z = newVelocity.z;
        }
Exemplo n.º 4
0
        private void HandleCollision(ref Vector4 velocity, PlayerEntity player, ICharacterControllerContext controller,
                                     float latestCollisionSlope)
        {
            // 碰到了天花板
            if ((controller.collisionFlags & CollisionFlags.Above) != 0)
            {
                player.playerMove.IsCollided = true;
                //只有在上跳的时候,把速度减为0
                if (velocity.y > 0)
                {
                    velocity.y = 0f;
                }
            }

            //collisionFlags会同时返回Above和Below
            if ((controller.collisionFlags & CollisionFlags.Below) != 0 ||
                (controller.collisionFlags & CollisionFlags.Sides) != 0)
            {
                player.playerMove.IsCollided = true;
                // 一个人往地面上的半球跳跃时,碰撞结果都是CollisionFlags.Sides,因此isGrounded为false
                // 1.如果Y轴分量大于0,则人物继续上升
                // 2.如果人物不能在碰撞点站住,则会加速下滑
                // 3.latestCollisionSlope < controller.slopeLimit条件一直不满足,角色一直下落,但是没有向下移动,可以认为CharacterController认为已经落地了,靠斜面下滑到latestCollisionSlope < controller.slopeLimit来最终落地
                if (velocity.y < 0 && (controller.isGrounded || latestCollisionSlope < controller.slopeLimit))
                {
                    if (latestCollisionSlope < controller.slopeLimit)
                    {
                        velocity.y = 0;
                    }
                    else
                    {
                        velocity.y = Mathf.Min(0f, player.playerMove.Velocity.y);
                    }
                    player.playerMove.IsGround = true;
                }
            }
        }
Exemplo n.º 5
0
 private bool IsSlideAloneSlope(ICharacterControllerContext controller, float angleOffset)
 {
     return(GroundInfo.IsSlideSlopeGround(controller.slopeLimit + angleOffset) && Vector3.Dot(LastNormal, Vector3.up) > 0.0f &&
            LastVelocity.y <= 0.0f && SharedConfig.EnableSlide);
 }
Exemplo n.º 6
0
        /// <summary>
        /// 旋转角色
        /// </summary>
        /// <param name="player"></param>
        /// <param name="deltaTime"></param>
        private static void RotateCharacter(PlayerEntity player, float deltaTime)
        {
            ICharacterControllerContext controller = player.characterContoller.Value;

            controller.Rotate(player.orientation.RotationYaw, deltaTime);
        }
 private static bool UseSphereCast(ICharacterControllerContext controller)
 {
     return(CompareUtility.IsApproximatelyEqual(controller.direction, Vector3.up));
 }
Exemplo n.º 8
0
 public void SetCharacterController(ICharacterControllerContext controller)
 {
     _controller = controller;
 }
Exemplo n.º 9
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();
            }
        }
Exemplo n.º 10
0
        private void CalculateVelocity(ref Vector4 velocity, ref Vector4 velocityOffset, ref float latestCollisionSlope,
                                       float deltaTime, PlayerEntity player, bool moveInWater, ICharacterControllerContext controller,
                                       Vector3 lastVel)
        {
            //坡度计算
            var lastNormal = controller.GetLastGroundNormal();

            // 最近一次与世界碰撞时碰撞点的法向
            latestCollisionSlope = Vector3.Angle(lastNormal, Vector3.up);

            //Debug.DrawRay(controller.GetLastGroundHitPoint(), lastNormal.normalized * 7,Color.yellow);

            Vector3 slopeVec = SlopeSlide(player, velocity, lastNormal, deltaTime);

            //Debug.DrawRay(controller.GetLastGroundHitPoint(), slopeVec.normalized * 7,Color.cyan);

            var xzcomp = Mathf.Sqrt(slopeVec.x * slopeVec.x + slopeVec.z * slopeVec.z);

            float collisionSlope = xzcomp == 0 ? 0 : slopeVec.y / xzcomp;


            var offsetSlope = Vector3.zero;

            //速度计算与下滑处理
            int ledgeDetect = -1;

            if (latestCollisionSlope >= controller.slopeLimit && Vector3.Dot(lastNormal, Vector3.up) > 0.0f &&
                (controller.collisionFlags & CollisionFlags.Below) != 0 &&
                lastVel.y <= 0.0f && (ledgeDetect = LedgeDetect(controller.GetLastGroundHitPoint(), controller.GetLastGroundNormal(),
                                                                controller.slopeLimit, controller.gameObject)) == 0
                )
            {
                // 沿斜面下滑
                velocity = slopeVec.ToVector4(); //SlopeSlide(player, -velocity.y, script.CollisionNormal, deltaTime);
                player.stateInterface.State.SetExceedSlopeLimit(true);
                //_logger.InfoFormat("slide slope!!!!!!, latestCollisionSlope:{0}", latestCollisionSlope);
            }
            else
            {
                var steepConfig = SingletonManager.Get <CharacterStateConfigManager>().SteepConfig;
                var buff        = steepConfig.CalcSteepBuff(player.playerMove.Steep) + (moveInWater ? -0.3f : 0) +
                                  player.playerMove.SpeedAffect;
                buff           = buff < -1.0f ? -1.0f : buff;
                velocity       = player.stateInterface.State.GetSpeed(lastVel, deltaTime, buff);
                velocityOffset = player.stateInterface.State.GetSpeedOffset(buff);
                velocity       = player.orientation.RotationYaw * (velocity);

                if (velocity.y < 0 &&
                    (Mathf.Abs(collisionSlope) > Mathf.Tan(MaxEdgeAngle * Mathf.Deg2Rad)) &&
                    (controller.collisionFlags & CollisionFlags.Below) != 0 && (ledgeDetect == -1 ? LedgeDetect(controller.GetLastGroundHitPoint(), controller.GetLastGroundNormal(),
                                                                                                                controller.slopeLimit, controller.gameObject):ledgeDetect) == 1)
                {
                    offsetSlope   = slopeVec;
                    offsetSlope.y = 0;
                    velocity.y    = slopeVec.y;
                    //_logger.InfoFormat("can not stand no ledge, ledgeDetect:{0}, collisionSlope:{1}, velocity:{2},offset:{3}, offsetSlope:{4},velocityOffset:{5}",
                    //   ledgeDetect,collisionSlope,
                    //  velocity.ToStringExt(),
                    //  (player.orientation.RotationYaw * (velocityOffset) + offsetSlope).ToStringExt(),
                    // offsetSlope.ToStringExt(),
                    // velocityOffset.ToStringExt());
                }

                else if (velocity.y < 0 &&
                         (Mathf.Abs(collisionSlope) < Mathf.Tan(controller.slopeLimit * Mathf.Deg2Rad)) && //超出限制应正常滑落
                         (controller.collisionFlags & CollisionFlags.Below) != 0
                         )                                                                                 //判断人物未浮空
                {
                    velocity.y = 0;
                    velocity.y = collisionSlope * velocity.magnitude - 0.1f; //-0.1f 保证下坡时持续产生CollisionFlags.Below
                    //_logger.InfoFormat("velocity:{0}, collisionSLocp:{1}, {2}, slopeVec:{3}, xzcomp:{4}", velocity.ToStringExt(), collisionSlope,Mathf.Tan(controller.slopeLimit * Mathf.Deg2Rad), slopeVec.ToStringExt() , xzcomp);
                }

                velocityOffset = player.orientation.RotationYaw * (velocityOffset) + offsetSlope;
                player.stateInterface.State.SetExceedSlopeLimit(false);
            }
        }