Advertisement
Polarwinds

SimpleEnemyAIBehavior

Oct 21st, 2014
420
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C# 22.11 KB | None | 0 0
  1.  
  2. using UnityEngine;
  3.  
  4. using System.Collections;
  5.  
  6.  
  7. public class AI : MonoBehaviour {
  8.  
  9.    
  10.  
  11.     //Inspector initiated variables. Defaults are set for ease of use.
  12.  
  13.     public bool on = true; //Is the AI active? this can be used to place pre-set enemies in you scene.
  14.  
  15.     public bool canFly = false; //Flying alters float behavior to ignore gravity. The enemy will fly up or down only to sustain floatHeight level.
  16.  
  17.     public float floatHeight = 0.0f; //If it can fly/hover, you need to let the AI know how high off the ground it should be.
  18.  
  19.     public bool runAway = false; //Is it the goal of this AI to keep it's distance? If so, it needs to have runaway active.
  20.  
  21.     public bool runTo = false; //Opposite to runaway, within a certain distance, the enemy will run toward the target.
  22.  
  23.     public float runDistance = 25.0f; //If the enemy should keep its distance, or charge in, at what point should they begin to run?
  24.  
  25.     public float runBufferDistance = 50.0f; //Smooth AI buffer. How far apart does AI/Target need to be before the run reason is ended.
  26.  
  27.     public int walkSpeed = 10; //Standard movement speed.
  28.  
  29.     public int runSpeed = 15; //Movement speed if it needs to run.
  30.  
  31.     public int randomSpeed = 10; //Movement speed if the AI is moving in random directions.
  32.  
  33.     public float rotationSpeed = 20.0f; //Rotation during movement modifier. If AI starts spinning at random, increase this value. (First check to make sure it's not due to visual radius limitations)
  34.  
  35.     public float visualRadius = 100.0f; //How close does the player need to be to be seen by the enemy? Set to 0 to remove this limitation.
  36.  
  37.     public float moveableRadius = 200.0f; //If the player is too far away, the AI will auto-matically shut down. Set to 0 to remove this limitation.
  38.  
  39.     public float attackRange = 10.0f; //How close does the enemy need to be in order to attack?
  40.  
  41.     public float attackTime = 0.50f; //How frequent or fast an enemy can attack (cool down time).
  42.  
  43.     public bool useWaypoints = false; //If true, the AI will make use of the waypoints assigned to it until over-ridden by another functionality.
  44.  
  45.     public bool reversePatrol = true; //if true, patrol units will walk forward and backward along their patrol.
  46.  
  47.     public Transform[] waypoints; //define a set path for them to follow.
  48.  
  49.     public bool pauseAtWaypoints = false; //if true, patrol units will pause momentarily at each waypoint as they reach them.
  50.  
  51.     public float pauseMin = 1.0f; //If pauseAtWaypoints is true, the unit will pause momentarily for minmum of this time.
  52.  
  53.     public float pauseMax = 3.0f; //If pauseAtWaypoints is true, the unit will pause momentarily formaximum of this time.
  54.  
  55.     public float huntingTimer = 5.0f; //Search for player timer in seconds. Minimum of 0.1
  56.  
  57.     public bool estimateElevation = false; //This implements a pause between raycasts for heights and guestimates the need to move up/down in height based on the previous raycast.
  58.  
  59.     public float estRayTimer = 1.0f; //The amount of time in seconds between raycasts for gravity and elevation checks.
  60.  
  61.     public bool requireTarget = true; //Waypoint ONLY functionality (still can fly and hover).
  62.  
  63.     public Transform target; //The target, or whatever the AI is looking for.
  64.  
  65.    
  66.  
  67.    
  68.  
  69.     //private script handled variables
  70.  
  71.     private bool initialGo = false; //AI cannot function until it is initialized.
  72.  
  73.     private bool go = true; //An on/off override variable
  74.  
  75.     private Vector3 lastVisTargetPos; //Monitor target position if we lose sight of target. provides semi-intelligent AI.
  76.  
  77.     CharacterController characterController; //CC used for enemy movement and etc.
  78.  
  79.     private bool playerHasBeenSeen = false; //An enhancement to how the AI functions prior to visibly seeing the target. Brings AI to life when target is close, but not visible.
  80.  
  81.     private bool enemyCanAttack = false; //Used to determine if the enemy is within range to attack, regardless of moving or not.
  82.  
  83.     private bool enemyIsAttacking = false; //An attack interuption method.
  84.  
  85.     private bool executeBufferState = false; //Smooth AI buffer for runAway AI. Also used as a speed control variable.
  86.  
  87.     private bool walkInRandomDirection = false; //Speed control variable.
  88.  
  89.     private float lastShotFired; //Used in conjuction with attackTime to monitor attack durations.
  90.  
  91.     private float lostPlayerTimer; //Used for hunting down the player.
  92.  
  93.     private bool targetIsOutOfSight; //Player tracking overload prevention. Makes sure we do not call the same coroutines over and over.
  94.  
  95.     private Vector3 randomDirection; //Random movement behaviour setting.
  96.  
  97.     private float randomDirectionTimer; //Random movement behaviour tracking.
  98.  
  99.     private float gravity = 20.0f; //force of gravity pulling the enemy down.
  100.  
  101.     private float antigravity = 2.0f; //force at which floating/flying enemies repel
  102.  
  103.     private float estHeight = 0.0f; //floating/flying creatures using estimated elevation use this to estimate height necessities and gravity impacts.
  104.  
  105.     private float estGravityTimer = 0.0f; //floating/flying creatures using estimated elevation will use this to actually monitor time values.
  106.  
  107.     private int estCheckDirection = 0; //used to determine if AI is falling or not when estimating elevation.
  108.  
  109.     private bool wpCountdown = false; //used to determine if we're moving forward or backward through the waypoints.
  110.  
  111.     private bool monitorRunTo = false; //when AI is set to runTo, they will charge in, and then not charge again to after far enough away.
  112.  
  113.     private int wpPatrol = 0; //determines what waypoint we are heading toward.
  114.  
  115.     private bool pauseWpControl; //makes sure unit pauses appropriately.
  116.  
  117.     private bool smoothAttackRangeBuffer = false; //for runAway AI to not be so messed up by their visual radius and attack range.
  118.  
  119.    
  120.  
  121.    
  122.  
  123.  
  124.     //---Starting/Initializing functions---//
  125.  
  126.     void Start() {
  127.  
  128.         StartCoroutine(Initialize()); //co-routine is used incase you need to interupt initiialization until something else is done.
  129.  
  130.     }
  131.  
  132.    
  133.  
  134.     IEnumerator Initialize() {
  135.  
  136.         if ((estimateElevation) && (floatHeight > 0.0f)) {
  137.  
  138.             estGravityTimer = Time.time;
  139.  
  140.         }
  141.  
  142.         characterController = gameObject.GetComponent<CharacterController>();
  143.  
  144.         initialGo = true;
  145.  
  146.         yield return null;
  147.  
  148.     }
  149.  
  150.    
  151.  
  152.    
  153.  
  154.    
  155.  
  156.     //---Main Functionality---//
  157.  
  158.     void Update () {
  159.  
  160.         if (!on || !initialGo) {
  161.  
  162.             return;
  163.  
  164.         } else {
  165.  
  166.             AIFunctionality();
  167.  
  168.         }
  169.  
  170.     }
  171.  
  172.    
  173.  
  174.     void AIFunctionality() {
  175.  
  176.         if ((!target) && (requireTarget)) {
  177.  
  178.             return; //if no target was set and we require one, AI will not function.
  179.  
  180.         }
  181.  
  182.        
  183.  
  184.         //Functionality Updates
  185.  
  186.         lastVisTargetPos = target.position; //Target tracking method for semi-intelligent AI
  187.  
  188.         Vector3 moveToward = lastVisTargetPos - transform.position; //Used to face the AI in the direction of the target
  189.  
  190.         Vector3 moveAway = transform.position - lastVisTargetPos; //Used to face the AI away from the target when running away
  191.  
  192.         float distance = Vector3.Distance(transform.position, target.position);
  193.  
  194.        
  195.  
  196.         if (go) {
  197.  
  198.             MonitorGravity();
  199.  
  200.         }
  201.  
  202.        
  203.  
  204.         if (!requireTarget) {
  205.  
  206.             //waypoint only functionality
  207.  
  208.             Patrol();
  209.  
  210.         } else if (TargetIsInSight ()) {
  211.  
  212.             if (!go) { //useWaypoints is false and the player has exceeded moveableRadius, shutdown AI until player is near.
  213.  
  214.                 return;
  215.  
  216.             }
  217.  
  218.            
  219.  
  220.             if ((distance > attackRange) && (!runAway) && (!runTo)) {
  221.  
  222.                 enemyCanAttack = false; //the target is too far away to attack
  223.  
  224.                 MoveTowards (moveToward); //move closer
  225.  
  226.             } else if ((smoothAttackRangeBuffer) && (distance > attackRange+5.0f)) {
  227.  
  228.                 smoothAttackRangeBuffer = false;
  229.  
  230.                 WalkNewPath();
  231.  
  232.             }else if ((runAway || runTo) && (distance > runDistance) && (!executeBufferState)) {
  233.  
  234.                 //move in random directions.
  235.  
  236.                 if (monitorRunTo) {
  237.  
  238.                     monitorRunTo = false;
  239.  
  240.                 }
  241.  
  242.                 if (runAway) {
  243.  
  244.                     WalkNewPath ();
  245.  
  246.                 } else {
  247.  
  248.                     MoveTowards (moveToward);
  249.  
  250.                 }
  251.  
  252.             } else if ((runAway || runTo) && (distance < runDistance) && (!executeBufferState)) { //make sure they do not get too close to the target
  253.  
  254.                 //AHH! RUN AWAY!...  or possibly charge :D
  255.  
  256.                 enemyCanAttack = false; //can't attack, we're running!
  257.  
  258.                 if (!monitorRunTo) {
  259.  
  260.                     executeBufferState = true; //smooth buffer is now active!
  261.  
  262.                 }
  263.  
  264.                 walkInRandomDirection = false; //obviously we're no longer moving at random.
  265.  
  266.                 if (runAway) {
  267.  
  268.                     MoveTowards (moveAway); //move away
  269.  
  270.                 } else {
  271.  
  272.                     MoveTowards (moveToward); //move toward
  273.  
  274.                 }
  275.  
  276.             } else if (executeBufferState && ((runAway) && (distance < runBufferDistance)) || ((runTo) && (distance > runBufferDistance))) {
  277.  
  278.                 //continue to run!
  279.  
  280.                 if (runAway) {
  281.  
  282.                     MoveTowards (moveAway); //move away
  283.  
  284.                 } else {
  285.  
  286.                     MoveTowards (moveToward); //move toward
  287.  
  288.                 }
  289.  
  290.             } else if ((executeBufferState) && (((runAway) && (distance > runBufferDistance)) || ((runTo) && (distance < runBufferDistance)))) {
  291.  
  292.                 monitorRunTo = true; //make sure that when we have made it to our buffer distance (close to user) we stop the charge until far enough away.
  293.  
  294.                 executeBufferState = false; //go back to normal activity
  295.  
  296.             }
  297.  
  298.  
  299.             //start attacking if close enough
  300.  
  301.             if ((distance < attackRange) || ((!runAway && !runTo) && (distance < runDistance))) {
  302.  
  303.                 if (runAway) {
  304.  
  305.                     smoothAttackRangeBuffer = true;
  306.  
  307.                 }
  308.  
  309.                 if (Time.time > lastShotFired + attackTime) {
  310.  
  311.                     StartCoroutine(Attack());
  312.  
  313.                 }
  314.  
  315.             }
  316.  
  317.            
  318.  
  319.         } else if ((playerHasBeenSeen) && (!targetIsOutOfSight) && (go)) {
  320.  
  321.             lostPlayerTimer = Time.time + huntingTimer;
  322.  
  323.             StartCoroutine(HuntDownTarget(lastVisTargetPos));
  324.  
  325.         } else if (useWaypoints) {
  326.  
  327.             Patrol();
  328.  
  329.         } else if (((!playerHasBeenSeen) && (go)) && ((moveableRadius == 0) || (distance < moveableRadius))){
  330.  
  331.             //the idea here is that the enemy has not yet seen the player, but the player is fairly close while still not visible by the enemy
  332.  
  333.             //it will move in a random direction continuously altering its direction every 2 seconds until it does see the player.
  334.  
  335.             WalkNewPath();
  336.  
  337.         }
  338.  
  339.     }
  340.  
  341.    
  342.  
  343.     //attack stuff...
  344.  
  345.     IEnumerator Attack() {
  346.  
  347.         enemyCanAttack = true;
  348.  
  349.        
  350.  
  351.         if (!enemyIsAttacking) {
  352.  
  353.             enemyIsAttacking = true;
  354.  
  355.             while (enemyCanAttack) {
  356.  
  357.                 lastShotFired = Time.time;
  358.  
  359.                 //implement attack variables here
  360.  
  361.                 yield return new WaitForSeconds(attackTime);
  362.  
  363.             }
  364.  
  365.         }
  366.  
  367.     }
  368.  
  369.    
  370.  
  371.    
  372.  
  373.    
  374.  
  375.     //----Helper Functions---//
  376.  
  377.     //verify enemy can see the target
  378.  
  379.     bool TargetIsInSight () {
  380.  
  381.         //determine if the enemy should be doing anything other than standing still
  382.  
  383.         if ((moveableRadius > 0) && (Vector3.Distance(transform.position, target.position) > moveableRadius)) {
  384.  
  385.             go = false;
  386.  
  387.         } else {
  388.  
  389.             go = true;
  390.  
  391.         }
  392.  
  393.        
  394.  
  395.         //then lets make sure the target is within the vision radius we allowed our enemy
  396.  
  397.         //remember, 0 radius means to ignore this check
  398.  
  399.         if ((visualRadius > 0) && (Vector3.Distance(transform.position, target.position) > visualRadius)) {
  400.  
  401.             return false;
  402.  
  403.         }
  404.  
  405.        
  406.  
  407.         //Now check to make sure nothing is blocking the line of sight
  408.  
  409.         RaycastHit sight;
  410.  
  411.         if (Physics.Linecast(transform.position, target.position, out sight)) {
  412.  
  413.             if (!playerHasBeenSeen && sight.transform == target) {
  414.  
  415.                 playerHasBeenSeen = true;
  416.  
  417.             }
  418.  
  419.             return sight.transform == target;
  420.  
  421.         } else {
  422.  
  423.             return false;
  424.  
  425.         }
  426.  
  427.     }
  428.  
  429.    
  430.  
  431.     //target tracking
  432.  
  433.     IEnumerator HuntDownTarget (Vector3 position) {
  434.  
  435.         //if this function is called, the enemy has lost sight of the target and must track him down!
  436.  
  437.         //assuming AI is not too intelligent, they will only move toward his last position, and hope they see him
  438.  
  439.         //this can be fixed later to update the lastVisTargetPos every couple of seconds to leave some kind of trail
  440.  
  441.         targetIsOutOfSight = true;
  442.  
  443.         while (targetIsOutOfSight) {
  444.  
  445.             Vector3 moveToward = position - transform.position;
  446.  
  447.             MoveTowards (moveToward);
  448.  
  449.            
  450.  
  451.             //check if we found the target yet
  452.  
  453.             if (TargetIsInSight ()) {
  454.  
  455.                 targetIsOutOfSight = false;
  456.  
  457.                 break;
  458.  
  459.             }
  460.  
  461.            
  462.  
  463.             //check to see if we should give up our search
  464.  
  465.             if (Time.time > lostPlayerTimer) {
  466.  
  467.                 targetIsOutOfSight = false;
  468.  
  469.                 playerHasBeenSeen = false;
  470.  
  471.                 break;
  472.  
  473.             }
  474.  
  475.             yield return null;
  476.  
  477.         }
  478.  
  479.     }
  480.  
  481.    
  482.  
  483.     void Patrol () {
  484.  
  485.         if (pauseWpControl) {
  486.  
  487.             return;
  488.  
  489.         }
  490.  
  491.         Vector3 destination = CurrentPath();
  492.  
  493.         Vector3 moveToward = destination - transform.position;
  494.  
  495.         float distance = Vector3.Distance(transform.position, destination);
  496.  
  497.         MoveTowards (moveToward);
  498.  
  499.         if (distance <= 1.5f+floatHeight) {// || (distance < floatHeight+1.5f)) {
  500.  
  501.             if (pauseAtWaypoints) {
  502.  
  503.                 if (!pauseWpControl) {
  504.  
  505.                     pauseWpControl = true;
  506.  
  507.                     StartCoroutine(WaypointPause());
  508.  
  509.                 }
  510.  
  511.             } else {
  512.  
  513.                 NewPath();
  514.  
  515.             }
  516.  
  517.         }
  518.  
  519.     }
  520.  
  521.    
  522.  
  523.     IEnumerator WaypointPause () {
  524.  
  525.         yield return new WaitForSeconds(Random.Range(pauseMin, pauseMax));
  526.  
  527.         NewPath();
  528.  
  529.         pauseWpControl = false;
  530.  
  531.     }
  532.  
  533.    
  534.  
  535.     Vector3 CurrentPath () {
  536.  
  537.         return waypoints[wpPatrol].position;
  538.  
  539.     }
  540.  
  541.    
  542.  
  543.     void NewPath () {
  544.  
  545.         if (!wpCountdown) {
  546.  
  547.             wpPatrol++;
  548.  
  549.             if (wpPatrol >= waypoints.GetLength(0)) {
  550.  
  551.                 if (reversePatrol) {
  552.  
  553.                     wpCountdown = true;
  554.  
  555.                     wpPatrol -= 2;
  556.  
  557.                 } else {
  558.  
  559.                     wpPatrol = 0;
  560.  
  561.                 }
  562.  
  563.             }
  564.  
  565.         } else if (reversePatrol) {
  566.  
  567.             wpPatrol--;
  568.  
  569.             if (wpPatrol < 0) {
  570.  
  571.                 wpCountdown = false;
  572.  
  573.                 wpPatrol = 1;
  574.  
  575.             }
  576.  
  577.         }
  578.  
  579.     }
  580.  
  581.    
  582.  
  583.     //random movement behaviour
  584.  
  585.     void WalkNewPath () {
  586.  
  587.         if (!walkInRandomDirection) {
  588.  
  589.             walkInRandomDirection = true;
  590.  
  591.             if (!playerHasBeenSeen) {
  592.  
  593.                 randomDirection = new Vector3(Random.Range(-0.15f,0.15f),0,Random.Range(-0.15f,0.15f));
  594.  
  595.             } else {
  596.  
  597.                 randomDirection = new Vector3(Random.Range(-0.5f,0.5f),0,Random.Range(-0.5f,0.5f));
  598.  
  599.             }
  600.  
  601.             randomDirectionTimer = Time.time;
  602.  
  603.         } else if (walkInRandomDirection) {
  604.  
  605.             MoveTowards (randomDirection);
  606.  
  607.         }
  608.  
  609.        
  610.  
  611.         if ((Time.time - randomDirectionTimer) > 2) {
  612.  
  613.             //choose a new random direction after 2 seconds
  614.  
  615.             walkInRandomDirection = false;
  616.  
  617.         }
  618.  
  619.     }
  620.  
  621.    
  622.  
  623.     //standard movement behaviour
  624.  
  625.     void MoveTowards (Vector3 direction) {
  626.  
  627.         direction.y = 0;
  628.  
  629.         int speed = walkSpeed;
  630.  
  631.        
  632.  
  633.         if (walkInRandomDirection) {
  634.  
  635.             speed = randomSpeed;
  636.  
  637.         }
  638.  
  639.        
  640.  
  641.         if (executeBufferState) {
  642.  
  643.             speed = runSpeed;
  644.  
  645.         }
  646.  
  647.        
  648.  
  649.         //rotate toward or away from the target
  650.  
  651.         transform.rotation = Quaternion.Slerp(transform.rotation, Quaternion.LookRotation(direction), rotationSpeed * Time.deltaTime);
  652.  
  653.         transform.eulerAngles = new Vector3(0, transform.eulerAngles.y, 0);
  654.  
  655.  
  656.         //slow down when we are not facing the target
  657.  
  658.         Vector3 forward = transform.TransformDirection(Vector3.forward);
  659.  
  660.         float speedModifier = Vector3.Dot(forward, direction.normalized);
  661.  
  662.         speedModifier = Mathf.Clamp01(speedModifier);
  663.  
  664.            
  665.  
  666.         //actually move toward or away from the target
  667.  
  668.         direction = forward * speed * speedModifier;
  669.  
  670.         if ((!canFly) && (floatHeight <= 0.0f)) {
  671.  
  672.             direction.y -= gravity;
  673.  
  674.         }
  675.  
  676.         characterController.Move(direction * Time.deltaTime);
  677.  
  678.     }
  679.  
  680.    
  681.  
  682.     //continuous gravity checks
  683.  
  684.     void MonitorGravity () {
  685.  
  686.         Vector3 direction = new Vector3(0, 0, 0);
  687.  
  688.        
  689.  
  690.         if ((!canFly) && (floatHeight > 0.0f)) {
  691.  
  692.             //we need to make sure our enemy is floating.. using evil raycasts! bwahahahah!
  693.  
  694.             if ((estimateElevation) && (estRayTimer > 0.0f)) {
  695.  
  696.                 if (Time.time > estGravityTimer) {
  697.  
  698.                     RaycastHit floatCheck;
  699.  
  700.                     if (Physics.Raycast(transform.position, -Vector3.up, out floatCheck)) {
  701.  
  702.                         if (floatCheck.distance < floatHeight-0.5f) {
  703.  
  704.                             estCheckDirection = 1;
  705.  
  706.                             estHeight = floatHeight - floatCheck.distance;
  707.  
  708.                         } else if (floatCheck.distance > floatHeight+0.5f) {
  709.  
  710.                             estCheckDirection = 2;
  711.  
  712.                             estHeight = floatCheck.distance - floatHeight;
  713.  
  714.                         } else {
  715.  
  716.                             estCheckDirection = 3;
  717.  
  718.                         }
  719.  
  720.                     } else {
  721.  
  722.                         estCheckDirection = 2;
  723.  
  724.                         estHeight = floatHeight*2;
  725.  
  726.                     }
  727.  
  728.                     estGravityTimer = Time.time + estRayTimer;
  729.  
  730.                 }
  731.  
  732.            
  733.  
  734.                 switch(estCheckDirection) {
  735.  
  736.                     case 1:
  737.  
  738.                         direction.y += antigravity;
  739.  
  740.                         estHeight -= direction.y * Time.deltaTime;
  741.  
  742.                         break;
  743.  
  744.                     case 2:
  745.  
  746.                         direction.y -= gravity;
  747.  
  748.                         estHeight -= direction.y * Time.deltaTime;
  749.  
  750.                         break;
  751.  
  752.                     default:
  753.  
  754.                         //do nothing
  755.  
  756.                         break;
  757.  
  758.                 }
  759.  
  760.                
  761.  
  762.             } else {
  763.  
  764.                 RaycastHit floatCheck;
  765.  
  766.                 if (Physics.Raycast(transform.position, -Vector3.up, out floatCheck, floatHeight+1.0f)) {
  767.  
  768.                     if (floatCheck.distance < floatHeight) {
  769.  
  770.                         direction.y += antigravity;
  771.  
  772.                     }
  773.  
  774.                 } else {
  775.  
  776.                     direction.y -= gravity;
  777.  
  778.                 }
  779.  
  780.             }
  781.  
  782.         } else {
  783.  
  784.             //bird like creature! Again with the evil raycasts! :p
  785.  
  786.             if ((estimateElevation) && (estRayTimer > 0.0f)) {
  787.  
  788.                 if (Time.time > estGravityTimer) {
  789.  
  790.                     RaycastHit floatCheck;
  791.  
  792.                     if (Physics.Raycast(transform.position, -Vector3.up, out floatCheck)) {
  793.  
  794.                         if (floatCheck.distance < floatHeight-0.5f) {
  795.  
  796.                             estCheckDirection = 1;
  797.  
  798.                             estHeight = floatHeight - floatCheck.distance;
  799.  
  800.                         } else if (floatCheck.distance > floatHeight+0.5f) {
  801.  
  802.                             estCheckDirection = 2;
  803.  
  804.                             estHeight = floatCheck.distance - floatHeight;
  805.  
  806.                         } else {
  807.  
  808.                             estCheckDirection = 3;
  809.  
  810.                         }
  811.  
  812.                     }
  813.  
  814.                     estGravityTimer = Time.time + estRayTimer;
  815.  
  816.                 }
  817.  
  818.                    
  819.  
  820.                 switch(estCheckDirection) {
  821.  
  822.                     case 1:
  823.  
  824.                         direction.y += antigravity;
  825.  
  826.                         estHeight -= direction.y * Time.deltaTime;
  827.  
  828.                         break;
  829.  
  830.                     case 2:
  831.  
  832.                         direction.y -= antigravity;
  833.  
  834.                         estHeight -= direction.y * Time.deltaTime;
  835.  
  836.                         break;
  837.  
  838.                     default:
  839.  
  840.                         //do nothing
  841.  
  842.                         break;
  843.  
  844.                 }
  845.  
  846.                    
  847.  
  848.             } else {
  849.  
  850.                 RaycastHit floatCheck;
  851.  
  852.                 if (Physics.Raycast(transform.position, -Vector3.up, out floatCheck)) {
  853.  
  854.                     if (floatCheck.distance < floatHeight-0.5f) {
  855.  
  856.                         direction.y += antigravity;
  857.  
  858.                     } else if (floatCheck.distance > floatHeight+0.5f) {
  859.  
  860.                         direction.y -= antigravity;
  861.  
  862.                     }
  863.  
  864.                 }
  865.  
  866.             }
  867.  
  868.         }
  869.  
  870.        
  871.  
  872.         if ((!estimateElevation) || ((estimateElevation) && (estHeight >= 0.0f))) {
  873.  
  874.             characterController.Move(direction * Time.deltaTime);
  875.  
  876.         }
  877.  
  878.     }
  879.  
  880.    
  881.  
  882. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement