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); }
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); }
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 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; } } }
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); }
/// <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)); }
public void SetCharacterController(ICharacterControllerContext controller) { _controller = controller; }
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(); } }
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); } }