/PlatformerProject/PlatformerProject/Scripts/2D/Character Controls/PlatformerController.cs
C# | 373 lines | 236 code | 74 blank | 63 comment | 41 complexity | 0c9648ac851248eb3fbe8e0a146fd66e MD5 | raw file
- using UnityEngine;
- using System.Collections;
-
- [RequireComponent (typeof(CharacterController))]
- [AddComponentMenu ("2D Platformer/Platformer Controller")]
- public class PlatformerController : MonoBehaviour
- {
- // Does this script currently respond to Input?
- public bool canControl = true;
-
- // The character will spawn at spawnPoint's position when needed. This could be changed via a script at runtime to implement, e.g. waypoints/savepoints.
- public Transform spawnPoint;
-
- public PlatformerControllerMovement movement = new PlatformerControllerMovement();
-
- public PlatformerControllerJumping jump = new PlatformerControllerJumping();
-
- public CharacterController controller;
-
- // Moving platform support.
- public Transform activePlatform;
- public Vector3 activeLocalPlatformPoint;
- public Vector3 activeGlobalPlatformPoint;
- public Vector3 lastPlatformVelocity;
-
- // This is used to keep track of special effects in UpdateEffects();
- bool areEmittersOn = false;
-
- // cache oft-used components
- Transform _transform;
-
-
- void Awake()
- {
- _transform = transform;
- movement.direction = _transform.TransformDirection(Vector3.forward);
- controller = GetComponent<CharacterController>();
- Spawn();
- }
-
- void Spawn()
- {
- // reset the character's speed
- movement.verticalSpeed = 0.0f;
- movement.speed = 0.0f;
-
- // reset the character's position to the spawnPoint
- _transform.position = spawnPoint.position;
- }
-
- void OnDeath()
- {
- Spawn();
- }
-
- void UpdateSmoothedMovementDirection()
- {
-
- float h = Input.GetAxisRaw("Horizontal");
-
- if (!canControl)
- h = 0.0f;
-
- movement.isMoving = Mathf.Abs(h) > 0.1f;
-
- if (movement.isMoving)
- {
- movement.direction = new Vector3(h, 0, 0);
- // sliding pseudo-code:
- // if(sliding_btn is down)
- // {
- // if(h == lastUpdate.h)
- // {
- // weAreSliding = true
- // if( slidingTime > howLongASlideLasts )
- // {
- // movement.direction = Vector3.zero;
- // weAreSliding = false
- // }
- // }
- // else
- // weAreSliding = false
- // }
-
- }
-
- // Ground controls
- if (controller.isGrounded)
- {
- // Smooth the sped based on the current target direction
- float curSmooth = movement.speedSmoothing * Time.deltaTime;
-
- // choose target speed
- float targetSpeed = Mathf.Min(Mathf.Abs(h), 1.0f);
-
- // This is where I'd put in speed adjustments for additional movements (ground)
-
-
- // for sliding for instance, we need to check for a button
- // then modify the speed
- // Pick speed modifier
- if (Input.GetButton("Fire2") && canControl)
- {
- targetSpeed *= movement.runSpeed;
- }
- else
- {
- targetSpeed *= movement.walkSpeed;
- }
-
- movement.speed = Mathf.Lerp(movement.speed, targetSpeed, curSmooth);
-
- movement.hangTime = 0.0f;
- }
- else // not grounded (in the air)
- {
- // In Air Controls
- movement.hangTime += Time.deltaTime;
- if (movement.isMoving)
- movement.inAirVelocity += new Vector3(Mathf.Sign(h), 0, 0) * Time.deltaTime;
- }
- }
-
- void FixedUpdate()
- {
- // force us to 2 Dimensions
- Vector3 p = _transform.position;
- p.z = 0;
- _transform.position = p;
- }
-
- void ApplyJumping()
- {
- // Prevent Jumping too fast after each other
- if (jump.lastTime + jump.repeatTime > Time.time)
- return;
-
- if (controller.isGrounded)
- {
- // Jump
- // - Only when pessing the button down
- // - With a timeout so you can press the button slightly before landing
- if (jump.enabled && Time.time < jump.lastButtonTime + jump.timeout)
- {
- movement.verticalSpeed = CalculateJumpVerticalSpeed(jump.height);
- movement.inAirVelocity = lastPlatformVelocity;
- SendMessage("DidJump", SendMessageOptions.DontRequireReceiver);
- }
- }
- }
-
- void ApplyGravity()
- {
- // Apply Gravity
- bool jumpButton = Input.GetButton("Jump");
-
- if (!canControl)
- jumpButton = false;
-
- // When we reach the apex of the jump we send out a message
- if (jump.jumping && !jump.reachedApex && movement.verticalSpeed <= 0.0f)
- {
- jump.reachedApex = true;
- SendMessage("DidJumpReachApex", SendMessageOptions.DontRequireReceiver);
- }
-
- // * When jumping up we don't apply gravity for some time when the user is holding the jump button
- // This gives more control over jump height by pressing the button longer
- bool extraPowerJump = jump.jumping && movement.verticalSpeed > 0.0f && jumpButton && transform.position.y < jump.lastStartHeight + jump.extraHeight && !IsTouchingCeiling;
-
- if (extraPowerJump)
- return;
- else if (controller.isGrounded)
- movement.verticalSpeed = -movement.gravity * Time.deltaTime;
- else
- movement.verticalSpeed -= movement.gravity * Time.deltaTime;
-
- // Make sure we don't fall any faster than maxFallSpeed. This gives our character a terminal velocity.
- movement.verticalSpeed = Mathf.Max(movement.verticalSpeed, -movement.maxFallSpeed);
- }
-
-
- float CalculateJumpVerticalSpeed(float targetJumpHeight)
- {
- // From the jump height and gravity we deduce the upwards speed
- // for the character to reach at the apex.
- return Mathf.Sqrt(2 * targetJumpHeight * movement.gravity);
- }
-
- void DidJump()
- {
- jump.jumping = true;
- jump.reachedApex = false;
- jump.lastTime = Time.time;
- jump.lastStartHeight = transform.position.y;
- jump.lastButtonTime = -10;
- }
-
- void UpdateEffects ()
- {
- bool wereEmittersOn = areEmittersOn;
- areEmittersOn = jump.jumping && movement.verticalSpeed > 0.0;
-
- // By comparing the previous value of areEmittersOn to the new one, we will only update the particle emitters when needed
- if (wereEmittersOn != areEmittersOn)
- {
- foreach(ParticleEmitter emitter in GetComponentsInChildren<ParticleEmitter> ())
- {
- emitter.emit = areEmittersOn;
- }
- }
- }
-
-
-
- void Update ()
- {
- Vector3 lastPosition;
- if (Input.GetButtonDown ("Jump") && canControl)
- {
- jump.lastButtonTime = Time.time;
- }
-
- UpdateSmoothedMovementDirection();
-
- // Apply gravity
- // - extra power jump modifies gravity
- ApplyGravity ();
-
- // Apply jumping logic
- ApplyJumping ();
-
- // Moving platform support
- if (activePlatform != null)
- {
- Vector3 newGlobalPlatformPoint = activePlatform.TransformPoint(activeLocalPlatformPoint);
- Vector3 moveDistance = (newGlobalPlatformPoint - activeGlobalPlatformPoint);
- _transform.position = _transform.position + moveDistance;
- lastPlatformVelocity = (newGlobalPlatformPoint - activeGlobalPlatformPoint) / Time.deltaTime;
- }
- else
- {
- lastPlatformVelocity = Vector3.zero;
- }
-
- activePlatform = null;
-
- // Save lastPosition for velocity calculation.
- lastPosition = _transform.position;
-
- // Calculate actual motion
- Vector3 currentMovementOffset = movement.direction * movement.speed + new Vector3 (0, movement.verticalSpeed, 0) + movement.inAirVelocity;
-
- // We always want the movement to be framerate independent. Multiplying by Time.deltaTime does this.
- currentMovementOffset *= Time.deltaTime;
-
- // Move our character!
- movement.collisionFlags = controller.Move (currentMovementOffset);
-
- // Calculate the velocity based on the current and previous position.
- // This means our velocity will only be the amount the character actually moved as a result of collisions.
- movement.velocity = (_transform.position - lastPosition) / Time.deltaTime;
-
- // Moving platforms support
- if (activePlatform != null) {
- activeGlobalPlatformPoint = transform.position;
- activeLocalPlatformPoint = activePlatform.InverseTransformPoint (transform.position);
- }
-
- // Set rotation to the move direction
- if (movement.direction.sqrMagnitude > 0.01)
- _transform.rotation = Quaternion.Slerp(transform.rotation, Quaternion.LookRotation(movement.direction), Time.deltaTime * movement.rotationSmoothing);
-
- // We are in jump mode but just became grounded
- if (controller.isGrounded)
- {
- movement.inAirVelocity = Vector3.zero;
- if (jump.jumping)
- {
- jump.jumping = false;
- SendMessage ("DidLand", SendMessageOptions.DontRequireReceiver);
-
- Vector3 jumpMoveDirection = movement.direction * movement.speed + movement.inAirVelocity;
- if (jumpMoveDirection.sqrMagnitude > 0.01)
- movement.direction = jumpMoveDirection.normalized;
- }
- }
-
- // Update special effects like rocket pack particle effects
- UpdateEffects ();
- }
-
- void OnControllerColliderHit (ControllerColliderHit hit)
- {
- Debug.Log("wtf? normal: " + hit.normal + ", direction: " + hit.moveDirection);
- if (hit.normal.y < -0.9f)
- {
- Debug.Log(hit.collider.gameObject.name);
- //controller.collider
- Physics.IgnoreCollision(hit.controller.collider, hit.collider, true);
- return;
- }
- if (hit.moveDirection.y > 0.01f)
- {
- Debug.Log(hit.collider.gameObject.name);
- //controller.collider
- Physics.IgnoreCollision(hit.controller.collider, hit.collider,true);
- return;
- }
-
- // Make sure we are really standing on a straight platform
- // Not on the underside of one and not falling down from it either!
- if (hit.moveDirection.y < -0.9f && hit.normal.y > 0.9f)
- {
- activePlatform = hit.collider.transform;
- }
- }
-
-
- public void Reset()
- {
- ////jump = new PlatformerControllerJumping();
- ////movement = new PlatformerControllerMovement();
- gameObject.tag = "Player";
- }
-
-
- #region props
-
- public float Speed
- {
- get{return movement.speed;}
- }
-
- public Vector3 Velocity
- {
- get{return movement.velocity;}
- }
-
-
- public bool IsMoving
- {
- get { return movement.isMoving; }
- }
-
- public bool IsJumping
- {
- get { return jump.jumping; }
- }
-
- public bool IsTouchingCeiling
- {
- get { return (movement.collisionFlags & CollisionFlags.CollidedAbove) != 0;}
- }
-
- public Vector3 Direction
- {
- get { return movement.direction; }
- }
-
- public float HangTime
- {
- get{return movement.hangTime; }
- }
- public bool Controllable
- {
- set { canControl = value; }
- get { return canControl; }
- }
- #endregion
- }
-
-