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; }
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); } }