private void Awake() { UpdateKinematics(); collisionController = GetComponent <CollisionController>(); dialogueManager = GetComponent <DialogueManager>(); // Quick hack, need this initialized on the first frame. collisionInfo = new CollisionController.CollisionInfo(); collisionInfo.colliders = new Dictionary <Vector3, Collider>(); soundController = GetComponent <SoundController>(); }
private void TriggerSolidCollidables() { // Get solid collidables from player movement and collisions. collInfo = playerMovement.GetCollisionInfo(); foreach (KeyValuePair <Vector3, Collider> pair in collInfo.colliders) { if (!collidableMap.ContainsKey(pair.Value)) { continue; } // Send collided signal. NB: the collision direction is inverted since the perspective changes to the other object. collidableMap[pair.Value].Collided(pair.Key * -1); } }
private void Update() { if (isRetrieving) { return; } child.Rotate(Vector3.forward * rotationSpeed * Time.deltaTime); // Calculate new velocity velocity.y = Mathf.Clamp(velocity.y + gravity * Time.deltaTime, -terminalVelocity, terminalVelocity); // Calculate new position and check for collisions. collisionInfo = collisionController.Check(velocity * Time.deltaTime); // Move to new position. transform.Translate(collisionInfo.moveVector); // React to collisions. if (collisionInfo.colliderHorizontal != null || collisionInfo.colliderVertical != null) { this.enabled = false; } }
public void Update() { if (coyoteTimeEnabled) { coyoteTimeLeft -= Time.deltaTime; // Get rid of primary jump if no coyote time is left. if (jumpsLeft == jumps && coyoteTimeLeft <= 0) { jumpsLeft--; } } else { // Get rid of primary jump if not on the ground. if (jumpsLeft == jumps && !collisionInfo.collisionBelow) { jumpsLeft--; } } // Register jump input ahead of time for buffer and use it if applicable, keep track of time since jump input. if (jumpBufferTimeLeft >= 0) { jumpBufferTimeLeft -= Time.deltaTime; } if (Input.GetKeyDown(KeyCode.Space)) { jumpBufferTimeLeft = jumpBufferTime; } // Calculate horizontal movement. float hInput = Input.GetAxisRaw("Horizontal"); // If we are sticking to wall, there's no horizontal movement to calculate. if (!(wallJumpingEnabled && wallStickingInfo.IsSticking())) { isRunning = true; if (walkingEnabled) { isRunning = Input.GetKey(KeyCode.LeftShift); } float targetSpeed = hInput * (isRunning ? runSpeed : walkSpeed); velocity.x = (velocity.x > targetSpeed) ? Mathf.Max(targetSpeed, velocity.x - (acceleration * Time.deltaTime)) : Mathf.Min(velocity.x + (acceleration * Time.deltaTime), targetSpeed); } // Special case: Wall jumping requires precise tricky timing of inputs. // Give the player a little bit of time to correct their mistake. if (toLaunchGracePeriodLeft > 0 && hInput == -wallDirection) { velocity.x = -wallDirection *Mathf.Cos(wallJumpLaunchAngle *Mathf.Deg2Rad); velocity.y = Mathf.Sin(wallJumpLaunchAngle * Mathf.Deg2Rad); velocity *= wallJumpLaunchSpeed; toLaunchGracePeriodLeft = -1; } // Calculate vertical movement. (By gravity or by jumping.) if (wallJumpingEnabled && toLaunchGracePeriodLeft > 0) { toLaunchGracePeriodLeft -= Time.deltaTime; } velocity.y = Mathf.Clamp(velocity.y + gravity * Time.deltaTime, -terminalVelocity, terminalVelocity); if (jumpBufferTimeLeft >= 0) { if (wallJumpingEnabled && wallStickingInfo.IsSticking()) { // Wall jump wallDirection = wallStickingInfo.GetWallDirection(); if (hInput == wallDirection) { velocity.x = -wallDirection *Mathf.Cos(wallJumpClimbAngle *Mathf.Deg2Rad); velocity.y = Mathf.Sin(wallJumpClimbAngle * Mathf.Deg2Rad); velocity *= wallJumpClimbSpeed; // Set launching grace period. toLaunchGracePeriodLeft = toLaunchGracePeriod; } else if (hInput == 0) { velocity.x = -wallDirection *Mathf.Cos(wallJumpHopAngle *Mathf.Deg2Rad); velocity.y = Mathf.Sin(wallJumpHopAngle * Mathf.Deg2Rad); velocity *= wallJumpHopSpeed; // Set launching grace period. toLaunchGracePeriodLeft = toLaunchGracePeriod; } else { velocity.x = -wallDirection *Mathf.Cos(wallJumpLaunchAngle *Mathf.Deg2Rad); velocity.y = Mathf.Sin(wallJumpLaunchAngle * Mathf.Deg2Rad); velocity *= wallJumpLaunchSpeed; } jumpBufferTimeLeft = -1; wallStickingInfo.Reset(); } else if (jumpsLeft > 0) { // Regular jumps velocity.y = (jumps == jumpsLeft ? maxJumpVelocity : maxMultiJumpVelocity); jumpsLeft--; // Just set the jump timer to negative to "consume" input. jumpBufferTimeLeft = -1; soundController.playJumpSound(); } } // Shortening jumps by releasing space. if (VariableJumpEnabled && Input.GetKeyUp(KeyCode.Space)) { if (jumps == jumpsLeft + 1) { if (velocity.y > minJumpVelocity) { velocity.y = minJumpVelocity; } } else { if (velocity.y > minMultiJumpVelocity) { velocity.y = minMultiJumpVelocity; } } } // Calculate change in position based on collisions. collisionInfo = collisionController.Check(velocity * Time.deltaTime); // React to vertical collisions. if (collisionInfo.colliderVertical != null) { velocity.y = 0; // If collision is below, reset jumping and coyote time (if enabled). if (collisionInfo.collisionBelow) { if (coyoteTimeEnabled) { coyoteTimeLeft = coyoteTime; } if (wallJumpingEnabled) { // Remove wall sticking if grounded. wallStickingInfo.Reset(); } jumpsLeft = jumps; } } // React to horizontal collisions. if (collisionInfo.colliderHorizontal != null) { velocity.x = 0; } if (wallJumpingEnabled) { wallStickingInfo.Tick(); } bool pushingAgainstWall = !collisionInfo.collisionBelow && ((collisionInfo.collisionRight && hInput == 1) || (collisionInfo.collisionLeft && hInput == -1)); // If we are pushing against a wall without any ground, reset stick. if (wallJumpingEnabled && pushingAgainstWall) { wallStickingInfo.Reset(collisionInfo.collisionRight ? 1 : -1, wallStickTime); } // If we are pushing against a wall or stuck to it, slide. if ((wallJumpingEnabled && wallStickingInfo.IsSticking()) || pushingAgainstWall) { // Sliding if (wallSlideEnabled && velocity.y < wallSlideSpeed) { velocity.y = -wallSlideSpeed; } } // Special case: If we are sticking but we aren't against a wall, stop sticking. (Usually happens when sliding off a wall.) if (wallJumpingEnabled && wallStickingInfo.IsSticking()) { if (!collisionController.Check(Vector2.right * 0.01f).collisionRight&& !collisionController.Check(Vector2.left * 0.01f).collisionLeft) { wallStickingInfo.Reset(); } } // Move the object. transform.Translate(collisionInfo.moveVector); }
private void Update() { if (coyoteTimeEnabled) { coyoteTimeLeft -= Time.deltaTime; // Get rid of primary jump if no coyote time is left. if (jumpsLeft == jumps && coyoteTimeLeft <= 0) { jumpsLeft--; } } else { // Get rid of primary jump if not on the ground. if (jumpsLeft == jumps && !collisionInfo.colliders.ContainsKey(Vector3.down)) { jumpsLeft--; } } // Register jump input ahead of time for buffer and use it if applicable, keep track of time since jump input. if (jumpBufferTimeLeft >= 0) { jumpBufferTimeLeft -= Time.deltaTime; } // Only do jumps if we are not in dialogue. if (Input.GetKeyDown(KeyCode.Space) && !dialogueManager.isOpen) { jumpBufferTimeLeft = jumpBufferTime; } // Calculate horizontal movement. /*TODO (possibly): hInput is not normalized. Meaning you cover more ground if you are traveling diagonally. * Mathematically, that is wrong: your top speed shouldn't increase if your heading changes. However, * in the game it FEELS better if you have acceleration. Which means I have to side with game feel. And it * bothers me so much. I don't know if I am doing something wrong with the numbers that I haven't noticed. * It's possible that because the player doesn't face the exact direction it is heading (it can only face the * four cardinal directions), when the player doesn't visually rotate but slows down in one axis when it is * normalized. Leading to bad game feel. I don't know.*/ Vector3 hInput = new Vector3(Input.GetAxisRaw("Horizontal"), 0, Input.GetAxisRaw("Vertical")) /*.normalized*/; // Cancel out hInput if we have dialogue open. if (dialogueManager.isOpen) { hInput = Vector3.zero; } velocity.x = (velocity.x > hInput.x * runSpeed) ? Mathf.Max(hInput.x * runSpeed, velocity.x - (acceleration * Time.deltaTime)) : Mathf.Min(velocity.x + (acceleration * Time.deltaTime), hInput.x * runSpeed); velocity.z = (velocity.z > hInput.z * runSpeed) ? Mathf.Max(hInput.z * runSpeed, velocity.z - (acceleration * Time.deltaTime)) : Mathf.Min(velocity.z + (acceleration * Time.deltaTime), hInput.z * runSpeed); // Always apply gravity. velocity.y = Mathf.Clamp(velocity.y + gravity * Time.deltaTime, -terminalVelocity, terminalVelocity); // Calculate vertical movement. if (jumpBufferTimeLeft >= 0 && jumpsLeft > 0) { velocity.y = (jumps == jumpsLeft ? maxJumpVelocity : maxMultiJumpVelocity); jumpsLeft--; soundController.PlayJumpSound(); // Just set the jump timer to negative to "consume" input. jumpBufferTimeLeft = -1; if (variableJumpEnabled) { variableJumpActive = true; } } // Shortening jumps by releasing space. if (variableJumpEnabled && Input.GetKeyUp(KeyCode.Space) && variableJumpActive) { variableJumpActive = false; if (jumps == jumpsLeft + 1) { if (velocity.y > minJumpVelocity) { velocity.y = minJumpVelocity; } } else { if (velocity.y > minMultiJumpVelocity) { velocity.y = minMultiJumpVelocity; } } } // Do the collision check. collisionInfo = collisionController.Check(velocity * Time.deltaTime); // If the ground is below us, stop. if (collisionInfo.colliders.ContainsKey(Vector3.down) || collisionInfo.colliders.ContainsKey(Vector3.up)) { velocity.y = 0; // If collision is below, reset jumping and coyote time (if enabled). if (collisionInfo.colliders.ContainsKey(Vector3.down)) { if (coyoteTimeEnabled) { coyoteTimeLeft = coyoteTime; } jumpsLeft = jumps; lastGroundedPosition = transform.position; } } // React to horizontal collisions. if (collisionInfo.colliders.ContainsKey(Vector3.right) || collisionInfo.colliders.ContainsKey(Vector3.left)) { velocity.x = 0; } if (collisionInfo.colliders.ContainsKey(Vector3.forward) || collisionInfo.colliders.ContainsKey(Vector3.back)) { velocity.z = 0; } // Move the player. transform.Translate(collisionInfo.moveVector); }