public override void KeyMovement(Vector3 moveDirection, MovementState movementState) { if (!CacheEntity.CanMove()) { return; } switch (CacheEntity.MovementSecure) { case MovementSecure.ServerAuthoritative: // Multiply with 100 and cast to sbyte to reduce packet size // then it will be devided with 100 later on server side CallNetFunction(NetFuncKeyMovement, DeliveryMethod.Sequenced, FunctionReceivers.Server, new DirectionVector3(moveDirection), movementState); break; case MovementSecure.NotSecure: tempInputDirection = moveDirection; tempMovementState = movementState; if (tempInputDirection.sqrMagnitude > 0) { navPaths = null; } if (canFly && !CacheOpenCharacterController.isGrounded && !isUnderWater && tempMovementState.HasFlag(MovementState.IsJump)) { isFlying = true; isJumping = false; applyingJumpForce = false; } if (!isJumping && !applyingJumpForce) { isJumping = (isUnderWater || CacheOpenCharacterController.isGrounded) && tempMovementState.HasFlag(MovementState.IsJump); } break; } }
protected void NetFuncPointClickMovement(Vector3 position) { if (!CacheEntity.CanMove()) { return; } tempMovementState = MovementState.Forward; SetMovePaths(position, true); }
protected void NetFuncUpdateYRotation(short yRotation) { if (!CacheEntity.CanMove()) { return; } if (!HasNavPaths) { this.yRotation = yRotation; UpdateRotation(); } }
public override void PointClickMovement(Vector3 position) { if (!CacheEntity.CanMove()) { return; } switch (CacheEntity.MovementSecure) { case MovementSecure.ServerAuthoritative: CallNetFunction(NetFuncPointClickMovement, FunctionReceivers.Server, position); break; case MovementSecure.NotSecure: tempMovementState = MovementState.Forward; SetMovePaths(position, true); break; } }
public override void SetLookRotation(Quaternion rotation) { if (!CacheEntity.CanMove()) { return; } switch (CacheEntity.MovementSecure) { case MovementSecure.ServerAuthoritative: // Cast to short to reduce packet size CallNetFunction(NetFuncUpdateYRotation, DeliveryMethod.Sequenced, FunctionReceivers.Server, (short)rotation.eulerAngles.y); break; case MovementSecure.NotSecure: if (!HasNavPaths) { yRotation = rotation.eulerAngles.y; } break; } }
protected void NetFuncKeyMovement(DirectionVector3 inputDirection, MovementState movementState) { if (!CacheEntity.CanMove()) { return; } tempInputDirection = inputDirection; tempMovementState = movementState; if (tempInputDirection.sqrMagnitude > 0) { navPaths = null; } if (canFly && !CacheOpenCharacterController.isGrounded && !isUnderWater && tempMovementState.HasFlag(MovementState.IsJump)) { isFlying = true; isJumping = false; applyingJumpForce = false; } if (!isJumping && !applyingJumpForce) { isJumping = (CacheOpenCharacterController.isGrounded || isUnderWater) && tempMovementState.HasFlag(MovementState.IsJump); } }
private void UpdateMovement(float deltaTime) { tempMoveVelocity = Vector3.zero; tempMoveDirection = Vector3.zero; tempTargetDistance = 0f; // Update airborne elasped if (CacheOpenCharacterController.isGrounded) { airborneElapsed = 0f; } else { airborneElapsed += deltaTime; } bool isGrounded = CacheOpenCharacterController.isGrounded || airborneElapsed < airborneDelay; if (isGrounded || !canFly) { isFlying = false; } if (HasNavPaths) { // Set `tempTargetPosition` and `tempCurrentPosition` tempTargetPosition = navPaths.Peek(); tempCurrentPosition = CacheTransform.position; tempTargetPosition.y = 0; tempCurrentPosition.y = 0; tempMoveDirection = tempTargetPosition - tempCurrentPosition; tempMoveDirection.Normalize(); tempTargetDistance = Vector3.Distance(tempTargetPosition, tempCurrentPosition); if (tempTargetDistance < StoppingDistance) { navPaths.Dequeue(); if (!HasNavPaths) { StopMove(); } } else { // Turn character to destination yRotation = Quaternion.LookRotation(tempMoveDirection).eulerAngles.y; } } // If move by WASD keys, set move direction to input direction if (tempInputDirection.sqrMagnitude > 0f) { tempMoveDirection = tempInputDirection; tempMoveDirection.Normalize(); } if (!CacheEntity.CanMove()) { tempMoveDirection = Vector3.zero; isJumping = false; applyingJumpForce = false; } // Prepare movement speed tempEntityMoveSpeed = applyingJumpForce ? 0f : CacheEntity.GetMoveSpeed(); if (isUnderWater) { isFlying = false; } tempCurrentMoveSpeed = tempEntityMoveSpeed * (isFlying ? flySpeed : isUnderWater ? swimSpeed : 1f); // Calculate vertical velocity by gravity if (!isGrounded && !isFlying) { if (!isUnderWater || submergence <= underWaterThreshold) { if (!useRootMotionForFall) { tempVerticalVelocity = Mathf.MoveTowards(tempVerticalVelocity, -maxFallVelocity, gravity * deltaTime); } else { tempVerticalVelocity = 0f; } } else { tempVerticalVelocity = 0f; } } else { tempVerticalVelocity = 0f; } // Jumping if (!isFlying && (isUnderWater || isGrounded) && isJumping) { if (!isUnderWater || submergence <= underWaterThreshold) { airborneElapsed = airborneDelay; CacheEntity.CallAllPlayJumpAnimation(); applyingJumpForce = true; applyJumpForceCountDown = 0f; switch (applyJumpForceMode) { case ApplyJumpForceMode.ApplyAfterFixedDuration: applyJumpForceCountDown = applyJumpForceFixedDuration; break; case ApplyJumpForceMode.ApplyAfterJumpDuration: if (CacheEntity.Model is IJumppableModel) { applyJumpForceCountDown = (CacheEntity.Model as IJumppableModel).GetJumpAnimationDuration(); } break; } } } if (applyingJumpForce) { applyJumpForceCountDown -= Time.deltaTime; if (applyJumpForceCountDown <= 0f) { applyingJumpForce = false; if (!useRootMotionForJump) { tempVerticalVelocity = CalculateJumpVerticalSpeed(); } } } // Updating horizontal movement (WASD inputs) if (tempMoveDirection.sqrMagnitude > 0f) { // Calculate only horizontal move direction tempHorizontalMoveDirection = tempMoveDirection; tempHorizontalMoveDirection.y = 0; tempHorizontalMoveDirection.Normalize(); // If character move backward if (Vector3.Angle(tempHorizontalMoveDirection, CacheTransform.forward) > 120) { tempCurrentMoveSpeed *= backwardMoveSpeedRate; } if (HasNavPaths) { // NOTE: `tempTargetPosition` and `tempCurrentPosition` were set above tempSqrMagnitude = (tempTargetPosition - tempCurrentPosition).sqrMagnitude; tempPredictPosition = tempCurrentPosition + (tempHorizontalMoveDirection * tempCurrentMoveSpeed * deltaTime); tempPredictSqrMagnitude = (tempPredictPosition - tempCurrentPosition).sqrMagnitude; // Check `tempSqrMagnitude` against the `tempPredictSqrMagnitude` // if `tempPredictSqrMagnitude` is greater than `tempSqrMagnitude`, // rigidbody will reaching target and character is moving pass it, // so adjust move speed by distance and time (with physic formula: v=s/t) if (tempPredictSqrMagnitude >= tempSqrMagnitude) { tempCurrentMoveSpeed *= tempTargetDistance / deltaTime / tempCurrentMoveSpeed; } tempMoveVelocity = tempHorizontalMoveDirection * tempCurrentMoveSpeed; } else { // Move with wasd keys so it does not have to adjust speed tempMoveVelocity = tempHorizontalMoveDirection * tempCurrentMoveSpeed; } } // Updating vertical movement (Fall, WASD inputs under water) if (isUnderWater || isFlying) { if (submergence >= underWaterThreshold || shouldDive || isFlying) { tempMoveVelocity.y = tempMoveDirection.y * tempCurrentMoveSpeed; shouldDive = false; } else { float distanceFromThreshold = underWaterThreshold - submergence; float bouyantVelocity = 0.01f; if (distanceFromThreshold > 0.01) { bouyantVelocity = -(distanceFromThreshold / deltaTime / tempCurrentMoveSpeed); } tempMoveVelocity.y = bouyantVelocity + (tempVerticalVelocity > 0 ? tempVerticalVelocity : 0f); } if (InputManager.GetButton("Crouch") || tempMoveDirection.y < -0.8) { shouldDive = true; } } else { // Update velocity while not under water tempMoveVelocity.y = tempVerticalVelocity; } collisionFlags = CacheOpenCharacterController.Move(tempMoveVelocity * deltaTime); if ((collisionFlags & CollisionFlags.CollidedBelow) == CollisionFlags.CollidedBelow || (collisionFlags & CollisionFlags.CollidedAbove) == CollisionFlags.CollidedAbove) { // Hit something below or above, falling in next frame tempVerticalVelocity = 0f; } UpdateRotation(); isJumping = false; }