Advertisement
Guest User

Untitled

a guest
Aug 30th, 2015
70
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C# 25.62 KB | None | 0 0
  1. using UnityEngine;
  2. using System.Collections;
  3. using System.Collections.Generic;
  4.  
  5. // Require a character controller to be attached to the same game object
  6. [RequireComponent(typeof(CharacterController))]
  7. [AddComponentMenu("Character/Character Motor")]
  8.  
  9.  
  10. public class CharacterMotor : MonoBehaviour
  11. {
  12.     // Does this script currently respond to input?
  13.     public bool canControl = true;
  14.     bool useFixedUpdate = true;
  15.  
  16.     // For the next variables, [System.NonSerialized] tells Unity to not serialize the variable or show it in the inspector view.
  17.     // Very handy for organization!
  18.  
  19.     // The current global direction we want the character to move in.
  20.     [System.NonSerialized]
  21.     public Vector3 inputMoveDirection = Vector3.zero;
  22.  
  23.     // Is the jump button held down? We use this interface instead of checking
  24.     // for the jump button directly so this script can also be used by AIs.
  25.     [System.NonSerialized]
  26.     public bool inputJump = false;
  27.  
  28.     [System.Serializable]
  29.     public class CharacterMotorMovement
  30.     {
  31.         // The maximum horizontal speed when moving
  32.         public float maxForwardSpeed = 3.0f;
  33.         public float maxSidewaysSpeed = 2.0f;
  34.         public float maxBackwardsSpeed = 2.0f;
  35.  
  36.         // Curve for multiplying speed based on slope(negative = downwards)
  37.         public AnimationCurve slopeSpeedMultiplier = new AnimationCurve(new Keyframe(-90, 1), new Keyframe(0, 1), new Keyframe(90, 0));
  38.  
  39.         // How fast does the character change speeds?  Higher is faster.
  40.         public float maxGroundAcceleration = 30.0f;
  41.         public float maxAirAcceleration = 20.0f;
  42.  
  43.         // The gravity for the character
  44.         public float gravity = 9.81f;
  45.         public float maxFallSpeed = 20.0f;
  46.  
  47.         // For the next variables, [System.NonSerialized] tells Unity to not serialize the variable or show it in the inspector view.
  48.         // Very handy for organization!
  49.  
  50.         // The last collision flags returned from controller.Move
  51.         [System.NonSerialized]
  52.         public CollisionFlags collisionFlags;
  53.  
  54.         // We will keep track of the character's current velocity,
  55.         [System.NonSerialized]
  56.         public Vector3 velocity;
  57.  
  58.         // This keeps track of our current velocity while we're not grounded
  59.         [System.NonSerialized]
  60.         public Vector3 frameVelocity = Vector3.zero;
  61.  
  62.         [System.NonSerialized]
  63.         public Vector3 hitPoint = Vector3.zero;
  64.  
  65.         [System.NonSerialized]
  66.         public Vector3 lastHitPoint = new Vector3(Mathf.Infinity, 0, 0);
  67.     }
  68.  
  69.     public CharacterMotorMovement movement = new CharacterMotorMovement();
  70.  
  71.     public enum MovementTransferOnJump
  72.     {
  73.         None, // The jump is not affected by velocity of floor at all.
  74.         InitTransfer, // Jump gets its initial velocity from the floor, then gradualy comes to a stop.
  75.         PermaTransfer, // Jump gets its initial velocity from the floor, and keeps that velocity until landing.
  76.         PermaLocked // Jump is relative to the movement of the last touched floor and will move together with that floor.
  77.     }
  78.  
  79.     // We will contain all the jumping related variables in one helper class for clarity.
  80.     [System.Serializable]
  81.     public class CharacterMotorJumping
  82.     {
  83.         // Can the character jump?
  84.         public bool enabled = true;
  85.  
  86.         // How high do we jump when pressing jump and letting go immediately
  87.         public float baseHeight = 1.0f;
  88.  
  89.         // We add extraHeight units(meters) on top when holding the button down longer while jumping
  90.         public float extraHeight = 4.1f;
  91.  
  92.         // How much does the character jump out perpendicular to the surface on walkable surfaces?
  93.         // 0 means a fully vertical jump and 1 means fully perpendicular.
  94.         public float perpAmount = 0.0f;
  95.  
  96.         // How much does the character jump out perpendicular to the surface on too steep surfaces?
  97.         // 0 means a fully vertical jump and 1 means fully perpendicular.
  98.         public float steepPerpAmount = 0.5f;
  99.  
  100.         // For the next variables, [System.NonSerialized] tells Unity to not serialize the variable or show it in the inspector view.
  101.         // Very handy for organization!
  102.  
  103.         // Are we jumping?(Initiated with jump button and not grounded yet)
  104.         // To see ifwe are just in the air(initiated by jumping OR falling) see the grounded variable.
  105.         [System.NonSerialized]
  106.         public bool jumping = false;
  107.  
  108.         [System.NonSerialized]
  109.         public bool holdingJumpButton = false;
  110.  
  111.         // the time we jumped at(Used to determine for how long to apply extra jump power after jumping.)
  112.         [System.NonSerialized]
  113.         public float lastStartTime = 0.0f;
  114.  
  115.         [System.NonSerialized]
  116.         public float lastButtonDownTime = -100.0f;
  117.  
  118.         [System.NonSerialized]
  119.         public Vector3 jumpDir = Vector3.up;
  120.     }
  121.  
  122.     public CharacterMotorJumping jumping = new CharacterMotorJumping();
  123.  
  124.     [System.Serializable]
  125.     public class CharacterMotorMovingPlatform
  126.     {
  127.         public bool enabled = true;
  128.  
  129.         public MovementTransferOnJump movementTransfer = MovementTransferOnJump.PermaTransfer;
  130.  
  131.         [System.NonSerialized]
  132.         public Transform hitPlatform;
  133.  
  134.         [System.NonSerialized]
  135.         public Transform activePlatform;
  136.  
  137.         [System.NonSerialized]
  138.         public Vector3 activeLocalPoint;
  139.  
  140.         [System.NonSerialized]
  141.         public Vector3 activeGlobalPoint;
  142.  
  143.         [System.NonSerialized]
  144.         public Quaternion activeLocalRotation;
  145.  
  146.         [System.NonSerialized]
  147.         public Quaternion activeGlobalRotation;
  148.  
  149.         [System.NonSerialized]
  150.         public Matrix4x4 lastMatrix;
  151.  
  152.         [System.NonSerialized]
  153.         public Vector3 platformVelocity;
  154.  
  155.         [System.NonSerialized]
  156.         public bool newPlatform;
  157.     }
  158.  
  159.     public CharacterMotorMovingPlatform movingPlatform = new CharacterMotorMovingPlatform();
  160.  
  161.     [System.Serializable]
  162.     public class CharacterMotorSliding
  163.     {
  164.         // Does the character slide on too steep surfaces?
  165.         public bool enabled = true;
  166.  
  167.         // How fast does the character slide on steep surfaces?
  168.         public float slidingSpeed = 15.0f;
  169.  
  170.         // How much can the player control the sliding direction?
  171.         // ifthe value is 0.5 the player can slide sideways with half the speed of the downwards sliding speed.
  172.         public float sidewaysControl = 1.0f;
  173.  
  174.         // How much can the player influence the sliding speed?
  175.         // ifthe value is 0.5 the player can speed the sliding up to 150% or slow it down to 50%.
  176.         public float speedControl = 0.4f;
  177.     }
  178.  
  179.     public CharacterMotorSliding sliding = new CharacterMotorSliding();
  180.  
  181.     [System.NonSerialized]
  182.     public bool grounded = true;
  183.  
  184.     [System.NonSerialized]
  185.     public Vector3 groundNormal = Vector3.zero;
  186.  
  187.     private Vector3 lastGroundNormal = Vector3.zero;
  188.  
  189.     private Transform tr;
  190.  
  191.     private CharacterController controller;
  192.  
  193.     void Awake()
  194.     {
  195.         controller = GetComponent<CharacterController>();
  196.         tr = transform;
  197.     }
  198.  
  199.     private void UpdateFunction()
  200.     {
  201.         // We copy the actual velocity into a temporary variable that we can manipulate.
  202.         Vector3 velocity = movement.velocity;
  203.  
  204.         // Update velocity based on input
  205.         velocity = ApplyInputVelocityChange(velocity);
  206.  
  207.         // Apply gravity and jumping force
  208.         velocity = ApplyGravityAndJumping(velocity);
  209.  
  210.         // Moving platform support
  211.         Vector3 moveDistance = Vector3.zero;
  212.         if(MoveWithPlatform())
  213.         {
  214.             Vector3 newGlobalPoint = movingPlatform.activePlatform.TransformPoint(movingPlatform.activeLocalPoint);
  215.             moveDistance = (newGlobalPoint - movingPlatform.activeGlobalPoint);
  216.             if(moveDistance != Vector3.zero)
  217.                 controller.Move(moveDistance);
  218.  
  219.             // Support moving platform rotation as well:
  220.             Quaternion newGlobalRotation = movingPlatform.activePlatform.rotation * movingPlatform.activeLocalRotation;
  221.             Quaternion rotationDiff = newGlobalRotation * Quaternion.Inverse(movingPlatform.activeGlobalRotation);
  222.  
  223.             var yRotation = rotationDiff.eulerAngles.y;
  224.             if(yRotation != 0)
  225.             {
  226.                 // Prevent rotation of the local up vector
  227.                 tr.Rotate(0, yRotation, 0);
  228.             }
  229.         }
  230.  
  231.         // Save lastPosition for velocity calculation.
  232.         Vector3 lastPosition = tr.position;
  233.  
  234.         // We always want the movement to be framerate independent.  Multiplying by Time.deltaTime does this.
  235.         Vector3 currentMovementOffset = velocity * Time.deltaTime;
  236.  
  237.         // Find out how much we need to push towards the ground to avoid loosing grouning
  238.         // when walking down a step or over a sharp change in slope.
  239.         float pushDownOffset = Mathf.Max(controller.stepOffset, new Vector3(currentMovementOffset.x, 0, currentMovementOffset.z).magnitude);
  240.         if(grounded)
  241.             currentMovementOffset -= pushDownOffset * Vector3.up;
  242.  
  243.         // Reset variables that will be set by collision function
  244.         movingPlatform.hitPlatform = null;
  245.         groundNormal = Vector3.zero;
  246.  
  247.         // Move our character!
  248.         movement.collisionFlags = controller.Move(currentMovementOffset);
  249.  
  250.         movement.lastHitPoint = movement.hitPoint;
  251.         lastGroundNormal = groundNormal;
  252.  
  253.         if(movingPlatform.enabled && movingPlatform.activePlatform != movingPlatform.hitPlatform)
  254.         {
  255.             if(movingPlatform.hitPlatform != null)
  256.             {
  257.                 movingPlatform.activePlatform = movingPlatform.hitPlatform;
  258.                 movingPlatform.lastMatrix = movingPlatform.hitPlatform.localToWorldMatrix;
  259.                 movingPlatform.newPlatform = true;
  260.             }
  261.         }
  262.  
  263.         // Calculate the velocity based on the current and previous position.  
  264.         // This means our velocity will only be the amount the character actually moved as a result of collisions.
  265.         Vector3 oldHVelocity = new Vector3(velocity.x, 0, velocity.z);
  266.         movement.velocity = (tr.position - lastPosition) / Time.deltaTime;
  267.         Vector3 newHVelocity = new Vector3(movement.velocity.x, 0, movement.velocity.z);
  268.  
  269.         // The CharacterController can be moved in unwanted directions when colliding with things.
  270.         // We want to prevent this from influencing the recorded velocity.
  271.         if(oldHVelocity == Vector3.zero)
  272.         {
  273.             movement.velocity = new Vector3(0, movement.velocity.y, 0);
  274.         }
  275.         else
  276.         {
  277.             float projectedNewVelocity = Vector3.Dot(newHVelocity, oldHVelocity) / oldHVelocity.sqrMagnitude;
  278.             movement.velocity = oldHVelocity * Mathf.Clamp01(projectedNewVelocity) + movement.velocity.y * Vector3.up;
  279.         }
  280.  
  281.         if(movement.velocity.y < velocity.y - 0.001)
  282.         {
  283.             if(movement.velocity.y < 0)
  284.             {
  285.                 // Something is forcing the CharacterController down faster than it should.
  286.                 // Ignore this
  287.                 movement.velocity.y = velocity.y;
  288.             }
  289.             else
  290.             {
  291.                 // The upwards movement of the CharacterController has been blocked.
  292.                 // This is treated like a ceiling collision - stop further jumping here.
  293.                 jumping.holdingJumpButton = false;
  294.             }
  295.         }
  296.  
  297.         // We were grounded but just loosed grounding
  298.         if(grounded && !IsGroundedTest())
  299.         {
  300.             grounded = false;
  301.  
  302.             // Apply inertia from platform
  303.             if(movingPlatform.enabled &&
  304.                 (movingPlatform.movementTransfer == MovementTransferOnJump.InitTransfer ||
  305.                 movingPlatform.movementTransfer == MovementTransferOnJump.PermaTransfer)
  306.             )
  307.             {
  308.                 movement.frameVelocity = movingPlatform.platformVelocity;
  309.                 movement.velocity += movingPlatform.platformVelocity;
  310.             }
  311.  
  312.             SendMessage("OnFall", SendMessageOptions.DontRequireReceiver);
  313.             // We pushed the character down to ensure it would stay on the ground ifthere was any.
  314.             // But there wasn't so now we cancel the downwards offset to make the fall smoother.
  315.             tr.position += pushDownOffset * Vector3.up;
  316.         }
  317.         // We were not grounded but just landed on something
  318.         else if(!grounded && IsGroundedTest())
  319.         {
  320.             grounded = true;
  321.             jumping.jumping = false;
  322.             SubtractNewPlatformVelocity();
  323.  
  324.             SendMessage("OnLand", SendMessageOptions.DontRequireReceiver);
  325.         }
  326.  
  327.         // Moving platforms support
  328.         if(MoveWithPlatform())
  329.         {
  330.             // Use the center of the lower half sphere of the capsule as reference point.
  331.             // This works best when the character is standing on moving tilting platforms.
  332.             movingPlatform.activeGlobalPoint = tr.position + Vector3.up * (controller.center.y - controller.height * 0.5f + controller.radius);
  333.             movingPlatform.activeLocalPoint = movingPlatform.activePlatform.InverseTransformPoint(movingPlatform.activeGlobalPoint);
  334.  
  335.             // Support moving platform rotation as well:
  336.             movingPlatform.activeGlobalRotation = tr.rotation;
  337.             movingPlatform.activeLocalRotation = Quaternion.Inverse(movingPlatform.activePlatform.rotation) * movingPlatform.activeGlobalRotation;
  338.         }
  339.     }
  340.  
  341.     void FixedUpdate()
  342.     {
  343.         if(movingPlatform.enabled)
  344.         {
  345.             if(movingPlatform.activePlatform != null)
  346.             {
  347.                 if(!movingPlatform.newPlatform)
  348.                 {
  349.                     // unused: Vector3 lastVelocity = movingPlatform.platformVelocity;
  350.  
  351.                     movingPlatform.platformVelocity = (
  352.                         movingPlatform.activePlatform.localToWorldMatrix.MultiplyPoint3x4(movingPlatform.activeLocalPoint)
  353.                         - movingPlatform.lastMatrix.MultiplyPoint3x4(movingPlatform.activeLocalPoint)
  354.                     ) / Time.deltaTime;
  355.                 }
  356.                 movingPlatform.lastMatrix = movingPlatform.activePlatform.localToWorldMatrix;
  357.                 movingPlatform.newPlatform = false;
  358.             }
  359.             else
  360.             {
  361.                 movingPlatform.platformVelocity = Vector3.zero;
  362.             }
  363.         }
  364.  
  365.         if(useFixedUpdate)
  366.             UpdateFunction();
  367.     }
  368.  
  369.     void Update()
  370.     {
  371.         if(!useFixedUpdate)
  372.             UpdateFunction();
  373.     }
  374.  
  375.     private Vector3 ApplyInputVelocityChange(Vector3 velocity)
  376.     {
  377.         if(!canControl)
  378.             inputMoveDirection = Vector3.zero;
  379.  
  380.         // Find desired velocity
  381.         Vector3 desiredVelocity;
  382.         if(grounded && TooSteep())
  383.         {
  384.             // The direction we're sliding in
  385.             desiredVelocity = new Vector3(groundNormal.x, 0, groundNormal.z).normalized;
  386.             // Find the input movement direction projected onto the sliding direction
  387.             var projectedMoveDir = Vector3.Project(inputMoveDirection, desiredVelocity);
  388.             // Add the sliding direction, the spped control, and the sideways control vectors
  389.             desiredVelocity = desiredVelocity + projectedMoveDir * sliding.speedControl + (inputMoveDirection - projectedMoveDir) * sliding.sidewaysControl;
  390.             // Multiply with the sliding speed
  391.             desiredVelocity *= sliding.slidingSpeed;
  392.         }
  393.         else
  394.             desiredVelocity = GetDesiredHorizontalVelocity();
  395.  
  396.         if(movingPlatform.enabled && movingPlatform.movementTransfer == MovementTransferOnJump.PermaTransfer)
  397.         {
  398.             desiredVelocity += movement.frameVelocity;
  399.             desiredVelocity.y = 0;
  400.         }
  401.  
  402.         if(grounded)
  403.             desiredVelocity = AdjustGroundVelocityToNormal(desiredVelocity, groundNormal);
  404.         else
  405.             velocity.y = 0;
  406.  
  407.         // Enforce max velocity change
  408.         float maxVelocityChange = GetMaxAcceleration(grounded) * Time.deltaTime;
  409.         Vector3 velocityChangeVector = (desiredVelocity - velocity);
  410.         if(velocityChangeVector.sqrMagnitude > maxVelocityChange * maxVelocityChange)
  411.         {
  412.             velocityChangeVector = velocityChangeVector.normalized * maxVelocityChange;
  413.         }
  414.         // ifwe're in the air and don't have control, don't apply any velocity change at all.
  415.         // ifwe're on the ground and don't have control we do apply it - it will correspond to friction.
  416.         if(grounded || canControl)
  417.             velocity += velocityChangeVector;
  418.  
  419.         if(grounded)
  420.         {
  421.             // When going uphill, the CharacterController will automatically move up by the needed amount.
  422.             // Not moving it upwards manually prevent risk of lifting off from the ground.
  423.             // When going downhill, DO move down manually, as gravity is not enough on steep hills.
  424.             velocity.y = Mathf.Min(velocity.y, 0);
  425.         }
  426.  
  427.         return velocity;
  428.     }
  429.  
  430.     private Vector3 ApplyGravityAndJumping(Vector3 velocity)
  431.     {
  432.  
  433.         if(!inputJump || !canControl)
  434.         {
  435.             jumping.holdingJumpButton = false;
  436.             jumping.lastButtonDownTime = -100;
  437.         }
  438.  
  439.         if(inputJump && jumping.lastButtonDownTime < 0 && canControl)
  440.             jumping.lastButtonDownTime = Time.time;
  441.  
  442.         if(grounded)
  443.             velocity.y = Mathf.Min(0, velocity.y) - movement.gravity * Time.deltaTime;
  444.         else
  445.         {
  446.             velocity.y = movement.velocity.y - movement.gravity * Time.deltaTime;
  447.  
  448.             // When jumping up we don't apply gravity for some time when the user is holding the jump button.
  449.             // This gives more control over jump height by pressing the button longer.
  450.             if(jumping.jumping && jumping.holdingJumpButton)
  451.             {
  452.                 // Calculate the duration that the extra jump force should have effect.
  453.                 // ifwe're still less than that duration after the jumping time, apply the force.
  454.                 if(Time.time < jumping.lastStartTime + jumping.extraHeight / CalculateJumpVerticalSpeed(jumping.baseHeight))
  455.                 {
  456.                     // Negate the gravity we just applied, except we push in jumpDir rather than jump upwards.
  457.                     velocity += jumping.jumpDir * movement.gravity * Time.deltaTime;
  458.                 }
  459.             }
  460.  
  461.             // Make sure we don't fall any faster than maxFallSpeed. This gives our character a terminal velocity.
  462.             velocity.y = Mathf.Max(velocity.y, -movement.maxFallSpeed);
  463.         }
  464.  
  465.         if(grounded)
  466.         {
  467.             // Jump only ifthe jump button was pressed down in the last 0.2 seconds.
  468.             // We use this check instead of checking ifit's pressed down right now
  469.             // because players will often try to jump in the exact moment when hitting the ground after a jump
  470.             // and ifthey hit the button a fraction of a second too soon and no new jump happens as a consequence,
  471.             // it's confusing and it feels like the game is buggy.
  472.             if(jumping.enabled && canControl && (Time.time - jumping.lastButtonDownTime < 0.2))
  473.             {
  474.                 grounded = false;
  475.                 jumping.jumping = true;
  476.                 jumping.lastStartTime = Time.time;
  477.                 jumping.lastButtonDownTime = -100;
  478.                 jumping.holdingJumpButton = true;
  479.  
  480.                 // Calculate the jumping direction
  481.                 if(TooSteep())
  482.                     jumping.jumpDir = Vector3.Slerp(Vector3.up, groundNormal, jumping.steepPerpAmount);
  483.                 else
  484.                     jumping.jumpDir = Vector3.Slerp(Vector3.up, groundNormal, jumping.perpAmount);
  485.  
  486.                 // Apply the jumping force to the velocity. Cancel any vertical velocity first.
  487.                 velocity.y = 0;
  488.                 velocity += jumping.jumpDir * CalculateJumpVerticalSpeed(jumping.baseHeight);
  489.  
  490.                 // Apply inertia from platform
  491.                 if(movingPlatform.enabled &&
  492.                     (movingPlatform.movementTransfer == MovementTransferOnJump.InitTransfer ||
  493.                     movingPlatform.movementTransfer == MovementTransferOnJump.PermaTransfer)
  494.                 )
  495.                 {
  496.                     movement.frameVelocity = movingPlatform.platformVelocity;
  497.                     velocity += movingPlatform.platformVelocity;
  498.                 }
  499.  
  500.                 SendMessage("OnJump", SendMessageOptions.DontRequireReceiver);
  501.             }
  502.             else
  503.             {
  504.                 jumping.holdingJumpButton = false;
  505.             }
  506.         }
  507.  
  508.         return velocity;
  509.     }
  510.  
  511.     void OnControllerColliderHit(ControllerColliderHit hit)
  512.     {
  513.         if(hit.normal.y > 0 && hit.normal.y > groundNormal.y && hit.moveDirection.y < 0)
  514.         {
  515.             if((hit.point - movement.lastHitPoint).sqrMagnitude > 0.001 || lastGroundNormal == Vector3.zero)
  516.                 groundNormal = hit.normal;
  517.             else
  518.                 groundNormal = lastGroundNormal;
  519.  
  520.             movingPlatform.hitPlatform = hit.collider.transform;
  521.             movement.hitPoint = hit.point;
  522.             movement.frameVelocity = Vector3.zero;
  523.         }
  524.     }
  525.  
  526.     private IEnumerator SubtractNewPlatformVelocity()
  527.     {
  528.         // When landing, subtract the velocity of the new ground from the character's velocity
  529.         // since movement in ground is relative to the movement of the ground.
  530.         if(movingPlatform.enabled &&
  531.           (movingPlatform.movementTransfer == MovementTransferOnJump.InitTransfer ||
  532.            movingPlatform.movementTransfer == MovementTransferOnJump.PermaTransfer))
  533.         {
  534.             // if we landed on a new platform, we have to wait for two FixedUpdates
  535.             // before we know the velocity of the platform under the character
  536.             if(movingPlatform.newPlatform)
  537.             {
  538.                 Transform platform = movingPlatform.activePlatform;
  539.                 yield return new WaitForFixedUpdate();
  540.                 yield return new WaitForFixedUpdate();
  541.                 if(grounded && platform == movingPlatform.activePlatform)
  542.                     yield break;
  543.             }
  544.             movement.velocity -= movingPlatform.platformVelocity;
  545.         }
  546.     }
  547.  
  548.     private bool MoveWithPlatform()
  549.     {
  550.         return (movingPlatform.enabled
  551.             && (grounded || movingPlatform.movementTransfer == MovementTransferOnJump.PermaLocked)
  552.             && movingPlatform.activePlatform != null
  553.         );
  554.     }
  555.  
  556.     private Vector3 GetDesiredHorizontalVelocity()
  557.     {
  558.         // Find desired velocity
  559.         Vector3 desiredLocalDirection = tr.InverseTransformDirection(inputMoveDirection);
  560.         float maxSpeed = MaxSpeedInDirection(desiredLocalDirection);
  561.         if(grounded)
  562.         {
  563.             // Modify max speed on slopes based on slope speed multiplier curve
  564.             var movementSlopeAngle = Mathf.Asin(movement.velocity.normalized.y) * Mathf.Rad2Deg;
  565.             maxSpeed *= movement.slopeSpeedMultiplier.Evaluate(movementSlopeAngle);
  566.         }
  567.         return tr.TransformDirection(desiredLocalDirection * maxSpeed);
  568.     }
  569.  
  570.     private Vector3 AdjustGroundVelocityToNormal(Vector3 hVelocity, Vector3 groundNormal)
  571.     {
  572.         Vector3 sideways = Vector3.Cross(Vector3.up, hVelocity);
  573.         return Vector3.Cross(sideways, groundNormal).normalized * hVelocity.magnitude;
  574.     }
  575.  
  576.     private bool IsGroundedTest()
  577.     {
  578.         return (groundNormal.y > 0.01);
  579.     }
  580.  
  581.     float GetMaxAcceleration(bool grounded)
  582.     {
  583.         // Maximum acceleration on ground and in air
  584.         if(grounded)
  585.             return movement.maxGroundAcceleration;
  586.         else
  587.             return movement.maxAirAcceleration;
  588.     }
  589.  
  590.     float CalculateJumpVerticalSpeed(float targetJumpHeight)
  591.     {
  592.         // From the jump height and gravity we deduce the upwards speed
  593.         // for the character to reach at the apex.
  594.         return Mathf.Sqrt(2 * targetJumpHeight * movement.gravity);
  595.     }
  596.  
  597.     bool IsJumping()
  598.     {
  599.         return jumping.jumping;
  600.     }
  601.  
  602.     bool IsSliding()
  603.     {
  604.         return (grounded && sliding.enabled && TooSteep());
  605.     }
  606.  
  607.     bool IsTouchingCeiling()
  608.     {
  609.         return (movement.collisionFlags & CollisionFlags.CollidedAbove) != 0;
  610.     }
  611.  
  612.     bool IsGrounded()
  613.     {
  614.         return grounded;
  615.     }
  616.  
  617.     bool TooSteep()
  618.     {
  619.         return (groundNormal.y <= Mathf.Cos(controller.slopeLimit * Mathf.Deg2Rad));
  620.     }
  621.  
  622.     Vector3 GetDirection()
  623.     {
  624.         return inputMoveDirection;
  625.     }
  626.  
  627.     void SetControllable(bool controllable)
  628.     {
  629.         canControl = controllable;
  630.     }
  631.  
  632.     // Project a direction onto elliptical quater segments based on forward, sideways, and backwards speed.
  633.     // The function returns the length of the resulting vector.
  634.     float MaxSpeedInDirection(Vector3 desiredMovementDirection)
  635.     {
  636.         if(desiredMovementDirection == Vector3.zero)
  637.             return 0;
  638.         else
  639.         {
  640.             float zAxisEllipseMultiplier = (desiredMovementDirection.z > 0 ? movement.maxForwardSpeed : movement.maxBackwardsSpeed) / movement.maxSidewaysSpeed;
  641.             Vector3 temp = new Vector3(desiredMovementDirection.x, 0, desiredMovementDirection.z / zAxisEllipseMultiplier).normalized;
  642.             float length = new Vector3(temp.x, 0, temp.z * zAxisEllipseMultiplier).magnitude * movement.maxSidewaysSpeed;
  643.             return length;
  644.         }
  645.     }
  646.  
  647.     void SetVelocity(Vector3 velocity)
  648.     {
  649.         grounded = false;
  650.         movement.velocity = velocity;
  651.         movement.frameVelocity = Vector3.zero;
  652.         SendMessage("OnExternalVelocity");
  653.     }
  654. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement