Advertisement
mvaganov

RBAgent.cs

May 14th, 2019
321
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C# 22.63 KB | None | 0 0
  1. using System;
  2. using System.Collections;
  3. using System.Collections.Generic;
  4. using UnityEngine;
  5. using Cinemachine.Utility;// for ProjectOntoPlane
  6. using UnityEngine.Serialization;
  7. using Random = UnityEngine.Random;
  8.  
  9. // TODO create the RBAgentCamera (and eyes) with a ContextMenuItem, or automatically if the agent is marked as Player
  10. // TODO ContextMenuItem to create sphere collider
  11. // TODO fix min/max pitch
  12. // TODO camera control variables to the RBAgentCamera
  13. // using Lines drawing code at: https://raw.githubusercontent.com/mvaganov/galactus/master/galactus/Assets/Nonstandard%20Assets/Lines.cs
  14.  
  15. [RequireComponent(typeof(Rigidbody))]
  16. public class RBAgent : MonoBehaviour {
  17.     [Serializable]
  18.     public struct CameraControls {
  19.         public Transform eyes;
  20.  
  21.         [Tooltip("If this is set, this agent will accept keyboard and mouse input as controls for velocity")]
  22.         public Camera cam;
  23.         [HideInInspector]
  24.         public RBAgentCamera rbcam;
  25.  
  26.         public float minPitch, maxPitch;
  27.         public float pitch;
  28.         public KeyCode toggleKey;// = KeyCode.None;
  29.  
  30.         public enum KindOfControls { FPS = 1, ClickToMove = 2, None = -1};
  31.  
  32.         public KindOfControls kindOfControls;
  33.         public enum MouseClick { mainClick=0, alternateClick=1, middleClick=2, none = -1}
  34.         public MouseClick clickToMove;
  35.  
  36.         public bool IsUpsidedown { get; private set; }
  37.         [HideInInspector]
  38.         public Quaternion targetForward;
  39.         /// the direction that the user wants to move forward in
  40.         [HideInInspector]
  41.         public Vector3 simpleForward;
  42.  
  43.         public void Init(Transform transform) {
  44.             if(cam != null && eyes != null) {
  45.                 rbcam = cam.GetComponent<RBAgentCamera>();
  46.                 if(rbcam == null) {
  47.                     rbcam = cam.gameObject.AddComponent<RBAgentCamera>();
  48.                 }
  49.                 rbcam.target = eyes;
  50.             }
  51.         }
  52.         public bool RotateBodyToMatchEyes(RBAgent a, bool turnBody) {
  53.             bool bodyRotationMade = false;
  54.             //float f = Mathf.Abs(pitch);
  55.             Vector3 properF = eyes.forward;//(f < 85 || f > 120)? eyes.forward : eyes.up;
  56.             simpleForward = properF.ProjectOntoPlane(a.gravity.Down);
  57.             if(simpleForward == Vector3.zero)
  58.                 simpleForward = properF.ProjectOntoPlane(eyes.up);
  59.             else
  60.                 simpleForward.Normalize();
  61.             targetForward = Quaternion.LookRotation(simpleForward, -a.gravity.Down);
  62.             float toRotateThisFrame = Time.deltaTime * a.Movement.RotationSpeed;
  63.             if(turnBody) {
  64.                 Quaternion lookRotationBeforeBodyShift = eyes.rotation;
  65.                 Quaternion next = Quaternion.RotateTowards(a.transform.rotation, targetForward, toRotateThisFrame);
  66.                 bodyRotationMade = next != a.transform.rotation;
  67.                 if(bodyRotationMade) {
  68.                     a.transform.rotation = next;
  69.                     eyes.rotation = lookRotationBeforeBodyShift;
  70.                 }
  71.             }
  72.             return bodyRotationMade;
  73.         }
  74.         public void UpdatePitch(RBAgent a) {
  75.             pitch = Vector3.Angle(-eyes.up, a.gravity.Down);
  76.             float alignedWithUp = Vector3.Dot(eyes.forward, -a.gravity.Down);
  77.             if(alignedWithUp > 0) pitch *= -1;
  78.             if(minPitch != maxPitch) {
  79.                 if(pitch < minPitch) {
  80.                     eyes.rotation = targetForward; eyes.Rotate(minPitch, 0, 0);
  81.                 }
  82.                 if(pitch > maxPitch) {
  83.                     eyes.rotation = targetForward; eyes.Rotate(maxPitch, 0, 0);
  84.                 }
  85.             }
  86.         }
  87.  
  88.         public void EnumToggle<T>(ref T value, T a, T b) {
  89.             value = (value.Equals(b))?a:b;
  90.         }
  91.        
  92.         public Vector3 GetDirectionBasedOnInput(RBAgent a) {
  93.             Vector3 dir = default(Vector3);
  94.             if(Input.GetKeyDown(toggleKey)) {
  95.                 EnumToggle(ref kindOfControls, KindOfControls.FPS, KindOfControls.ClickToMove);
  96.                 if(clickToMove != MouseClick.none) {
  97.                     a.aiMovement.moveToTarget = kindOfControls == KindOfControls.ClickToMove;
  98.                     if(a.aiMovement.moveToTarget) {
  99.                         a.aiMovement.targetLocation = a.transform.position;
  100.                         rbcam.boundToTargetDirection = false;
  101.                     } else {
  102.                         eyes.rotation = rbcam.transform.rotation;
  103.                         rbcam.boundToTargetDirection = true;
  104.                     }
  105.                 }
  106.             }
  107.             if(kindOfControls == KindOfControls.FPS) {
  108.                 float h = Input.GetAxis("Horizontal"), v = Input.GetAxis("Vertical");
  109.                 if(h != 0 || v != 0) {
  110.                     if(h != 0) { dir += Vector3.Cross(simpleForward, a.gravity.Down) * h; }
  111.                     if(v != 0) { dir += simpleForward * v; }
  112.                     if(!a.gravity.IgnoreGravityPull) {
  113.                         dir = dir.ProjectOntoPlane(a.gravity.Down);
  114.                         dir.Normalize();
  115.                     }
  116.                 }
  117.             } else if(a.aiMovement != null && a.cameraControls.toggleKey != KeyCode.None) {
  118.                 Vector2 mouseDelta = new Vector2(Input.GetAxis("Horizontal"), Input.GetAxis("Vertical"));
  119.                 rbcam.playerTurningCamera = mouseDelta != Vector2.zero;
  120.                 if(rbcam.playerTurningCamera) {
  121.                     RotateCamera(a, mouseDelta);
  122.                 }
  123.             }
  124.             return dir;
  125.         }
  126.         public void RotateCamera(RBAgent a, Vector2 mouse) {
  127.             if(mouse != Vector2.zero) {
  128.                 if(mouse.y != 0) { eyes.Rotate(-mouse.y * a.Movement.CameraTurn, 0, 0); }
  129.                 if(rbcam.distance != 0) { // don't restrict pitch of FPS mode
  130.                     UpdatePitch(a);
  131.                 } else {
  132.                     pitch = eyes.rotation.eulerAngles.x;
  133.                     if(pitch > 180) pitch -= 360;
  134.                 }
  135.                 if(mouse.x != 0) {
  136.                     eyes.Rotate(-pitch, 0, 0);
  137.                     eyes.Rotate(0, mouse.x * a.Movement.CameraTurn, 0);
  138.                     eyes.Rotate(pitch, 0, 0);
  139.                 }
  140.                 RefreshCameraOrientationBasedOnUp(a, eyes);
  141.             }
  142.         }
  143.         public void SetEyeDirectionbasedOnInput(RBAgent a){
  144.             if(kindOfControls == KindOfControls.FPS) {
  145.                 Vector2 mouse = new Vector2(Input.GetAxis("Mouse X"), Input.GetAxis("Mouse Y"));
  146.                 RotateCamera(a, mouse);
  147.             }
  148.         }
  149.         public void RefreshCameraOrientationBasedOnUp(RBAgent a, Transform toAlign) {
  150.             float alignedWithUp = Vector3.Dot(-a.gravity.Down, toAlign.up);
  151.             IsUpsidedown = alignedWithUp < 0;
  152.             //Vector3 r = Vector3.Cross(simpleForward, a.gravity.down), angledUp;
  153.             Vector3 r = Vector3.Cross(toAlign.forward, a.gravity.Down), angledUp;
  154.             r.Normalize();
  155.             angledUp = Vector3.Cross(toAlign.forward, r);
  156.             // make sure the camera is oriented correctly
  157.             eyes.rotation = Quaternion.RotateTowards(toAlign.rotation,
  158.                 Quaternion.LookRotation(toAlign.forward, angledUp),
  159.                 a.gravity.GravityTurnSpeed * Time.deltaTime);
  160.             //Debug.Log("ROTATING");
  161.         }
  162.         public void ZoomBasedOnInput(RBAgent a) {
  163.             if(kindOfControls != KindOfControls.None) {
  164.                 float scrollWheel = Input.GetAxis("Mouse ScrollWheel");
  165.                 if(scrollWheel != 0) {
  166.                     rbcam.distance += scrollWheel;
  167.                     if(rbcam.distance < 0) { rbcam.distance = 0; }
  168.                 }
  169.             }
  170.         }
  171.         public void ClickToMove(RBAgent a) {
  172.             if(cam != null && Input.GetMouseButtonDown((int)clickToMove)) {
  173.                 Ray r = cam.ScreenPointToRay(Input.mousePosition);
  174.                 RaycastHit rh = new RaycastHit();
  175.                 if(Physics.Raycast(r, out rh)) {
  176.                     a.aiMovement.targetLocation = rh.point;
  177.                 }
  178.                 if(a.aiMovement.RandomWalk != null) {
  179.                     a.aiMovement.RandomWalk.SetRandomWalkTime(float.NegativeInfinity);
  180.                 }
  181.             }
  182.         }
  183.  
  184.     }
  185.     public CameraControls cameraControls = new CameraControls {
  186.         kindOfControls = CameraControls.KindOfControls.FPS, minPitch=-80, maxPitch=120
  187.     };
  188.  
  189.     [System.Serializable]
  190.     public class AIMovement {
  191.         public bool moveToTarget;
  192.         public Vector3 targetLocation;
  193.  
  194.         /// Gets the direction toward target.
  195.         /// <returns>The direction toward target, or Vector3.zero if agent has arrived</returns>
  196.         /// <param name="a">The alpha component.</param>
  197.         /// <param name="alsoTurn">If set to <c>true</c> also turn.</param>
  198.         public Vector3 GetDirectionTowardTarget(RBAgent a, bool alsoTurn = true) {
  199.             Vector3 delta = targetLocation - a.transform.position;
  200.             if(!a.gravity.IgnoreGravityPull) {
  201.                 delta = delta.ProjectOntoPlane(a.gravity.Down);
  202.                 targetLocation = a.transform.position + delta;
  203.                 if(a.debugLineColor.a > 0) {
  204.                     NS.Lines.MakeCircle(ref a.line_target, targetLocation, a.gravity.Down, a.debugLineColor);
  205.                 }
  206.             }
  207.             float dist = delta.magnitude;
  208.             Vector3 dir = Vector3.zero;
  209.             if(dist != 0) {
  210.                 if(dist < .125f) {
  211.                     if(RandomWalk.Enabled) {
  212.                         RandomWalk.QueueUpdate();
  213.                     } else {
  214.                         return Vector3.zero;
  215.                     }
  216.                 }
  217.                 dir = delta / dist;
  218.                 dir.Normalize();
  219.                 if(alsoTurn) {
  220.                     Quaternion targetRotation = Quaternion.LookRotation(dir, -a.gravity.Down);
  221.                     a.transform.rotation = Quaternion.RotateTowards(a.transform.rotation, targetRotation, Time.deltaTime * a.Movement.RotationSpeed);
  222.                 }
  223.             }
  224.             return dir;
  225.         }
  226.  
  227.         [System.Serializable]
  228.         public class RandomWalkDetails {
  229.             [FormerlySerializedAs("enabled")] public bool Enabled;
  230.             [FormerlySerializedAs("duration")] public float Duration;
  231.             [FormerlySerializedAs("durationWiggleRoom")] public float DurationWiggleRoom;
  232.             private float _timer;
  233.             public void SetRandomWalkTime(float t) { _timer = t; }
  234.             public void Update(Action action) {
  235.                 _timer += Time.deltaTime;
  236.                 if (_timer < Duration) return;
  237.                 _timer -= Duration;
  238.                 _timer -= Random.Range(-DurationWiggleRoom, DurationWiggleRoom);
  239.                 action.Invoke();
  240.             }
  241.             public void QueueUpdate() { _timer = Duration; }
  242.         }
  243.         public RandomWalkDetails RandomWalk = new RandomWalkDetails {
  244.             Enabled = true, Duration = 2, DurationWiggleRoom = 0.5f
  245.         };
  246.     }
  247.     public AIMovement aiMovement = new AIMovement { moveToTarget = true };
  248.  
  249.  
  250.     [Serializable]
  251.     public struct Move {
  252.         [Tooltip("speed of agent")]
  253.         public float Speed;
  254.         [Tooltip("how quickly the body turns (degrees per second)")]
  255.         public float RotationSpeed;
  256.         [Tooltip("how quickly the camera turns (multiplies mouse movement / keyboard input)")]
  257.         public float CameraTurn;
  258.         /// what direction the agent is going in
  259.         [HideInInspector]
  260.         public Vector3 Direction;
  261.     }
  262.     [ContextMenuItem("create move modifier", "CreateMoveModifier")]
  263.     public Move Movement = new Move{Speed = 3, RotationSpeed = 180, CameraTurn = 5 };
  264.  
  265.     private void CreateMoveModifier(){ gameObject.AddComponent<MoveModifier>();}
  266.    
  267.     public class MoveModifier : MonoBehaviour {
  268.         public KeyCode RunKey = KeyCode.LeftShift;
  269.         public float MoveMultiplier = 2; private float _originalSpeed;
  270.         public float MaxStandAngle = 10; private float _originalStandAngle;
  271.         private bool _running;
  272.         private RBAgent _rba;
  273.         void Start() {
  274.             _rba = GetComponent<RBAgent>();
  275.             _originalSpeed = _rba.Movement.Speed;
  276.             _originalStandAngle = _rba.stand.maxStandAngle;
  277.         }
  278.         void Update() {
  279.             bool runningNow = Input.GetKey(RunKey);
  280.             if (runningNow && !_running) {
  281.                 _rba.Movement.Speed = _originalSpeed * MoveMultiplier;
  282.                 _rba.stand.maxStandAngle = MaxStandAngle;
  283.             } else if (!runningNow && _running) {
  284.                 _rba.Movement.Speed = _originalSpeed;
  285.                 _rba.stand.maxStandAngle = _originalStandAngle;
  286.             }
  287.             _running = runningNow;
  288.         }
  289.     }
  290.  
  291.     [System.Serializable]
  292.     public struct Gravity {
  293.         public Vector3 Down;
  294.         public float Force;
  295.         [Tooltip("how quickly to reorient the camera when the direction of gravity changes (degrees per second)")]
  296.         public float GravityTurnSpeed;
  297.         [HideInInspector]
  298.         public float Distance;
  299.         public Vector3 Calculate(RBAgent a, bool a_ignoreGravityPull) {
  300.             if(UseGravityPoint) {
  301.                 Vector3 lastGravity = Down;
  302.                 Down = GravityCenter - a.transform.position;
  303.                 Distance = Down.magnitude;
  304.                 Down /= Distance;
  305.                 if(Down != lastGravity) {
  306.                     Quaternion oldFacing = a.transform.rotation;
  307.                     Transform viewer = (a.cameraControls.kindOfControls == CameraControls.KindOfControls.FPS)
  308.                         ?a.cameraControls.eyes:(a.cameraControls.rbcam.transform
  309.                             ?a.cameraControls.rbcam.transform:null);
  310.                     if(viewer) {
  311.                         Transform oldParent = a.transform;
  312.                         if(viewer.parent != a.transform) {
  313.                             oldParent = viewer.parent;
  314.                             viewer.SetParent(a.transform);
  315.                         }
  316.                         Vector3 localVelocity = Vector3.zero;
  317.                         Quaternion localLook = viewer.localRotation;
  318.                         if(!UseUncurvedVelocity) {
  319.                             localVelocity = a.transform.InverseTransformVector(a.rb.velocity);
  320.                         }
  321.                         Vector3 simpleBodyForward = a.transform.forward.ProjectOntoPlane(Down);
  322.                         simpleBodyForward.Normalize();
  323.                         Quaternion nextIdealBodyFace = Quaternion.LookRotation(simpleBodyForward, -Down);
  324.                         a.transform.rotation = Quaternion.RotateTowards(a.transform.rotation, nextIdealBodyFace, GravityTurnSpeed * Time.deltaTime);
  325.                         if(!UseUncurvedVelocity) {
  326.                             a.rb.velocity = a.transform.TransformVector(localVelocity);
  327.                         }
  328.                         a.cameraControls.RefreshCameraOrientationBasedOnUp(a, viewer);
  329.                         viewer.localRotation = localLook;
  330.                         if(viewer.parent != oldParent) {
  331.                             viewer.SetParent(oldParent);
  332.                         }
  333.                     }
  334.                 }
  335.             } else {
  336.                 Distance = 0;
  337.             }
  338.             if(!IgnoreGravityPull && !a_ignoreGravityPull) {
  339.                 a.rb.velocity += Down * (Force * Time.deltaTime);
  340.             }
  341.             return Down;
  342.         }
  343.         public bool UseGravityPoint;
  344.         public bool IgnoreGravityPull;
  345.         public bool UseUncurvedVelocity;
  346.         public Vector3 GravityCenter;
  347.     }
  348.     public Gravity gravity = new Gravity { Down = Vector3.down, Force = 10, GravityTurnSpeed = 360 };
  349.  
  350.     [System.Serializable]
  351.     public struct Standing {
  352.         public float standAngle;
  353.         public float maxStandAngle;
  354.         public float maxStandHeight;
  355.         public float minStandHeight;
  356.         [HideInInspector]
  357.         public bool IsStanding, IsWalkable;
  358.         public bool wontGrabWalls;
  359.         public bool wontStabalizeFooting;
  360.         public Ray standRay;
  361.         public RaycastHit standHit;
  362.         private Vector3 standOffset, standRayDir;
  363.         public float standRadius;
  364.         public void FixedUpdate(RBAgent a) {
  365.             standRay = new Ray(a.transform.position + standOffset, standRayDir);
  366.             if(Physics.Raycast(standRay, out standHit, maxStandHeight) && standHit.collider.gameObject != a.gameObject) {
  367.                 standAngle = Vector3.Angle(standHit.normal, -a.gravity.Down);
  368.                 IsStanding = standAngle < maxStandAngle;
  369.                 // down hill is a negative stand angle
  370.                 float goingInTheSameDirection = Vector3.Dot(a.GetMoveForward(), standHit.normal);
  371.                 if(goingInTheSameDirection > 0) { standAngle *= -1; }
  372.             } else {
  373.                 standAngle = float.PositiveInfinity;
  374.                 IsStanding = false;
  375.             }
  376.             IsWalkable = standAngle < maxStandAngle;
  377.             if(!IsStanding) {
  378.                 standRayDir = wontGrabWalls? a.gravity.Down :
  379.                                               (a.gravity.Down + Random.insideUnitSphere).normalized + a.cameraControls.simpleForward;
  380.                 standOffset = Random.insideUnitSphere.ProjectOntoPlane(standRayDir) * standRadius;
  381.             }
  382.             if(IsStanding && !a.jump.IsJumping) {
  383.                 if(standHit.distance > minStandHeight) {
  384.                     Vector3 targetLoc = standHit.point - standOffset - standRayDir * minStandHeight;
  385.                     a.transform.position = Vector3.MoveTowards(
  386.                         a.transform.position, targetLoc, a.Movement.Speed * Time.deltaTime);
  387.                 } else if(!wontStabalizeFooting && standRayDir != a.gravity.Down) {
  388.                     standRayDir = a.gravity.Down;
  389.                     Vector3 targetLoc = standHit.point - standOffset - standRayDir * minStandHeight;
  390.                     a.transform.position = Vector3.MoveTowards(
  391.                         a.transform.position, targetLoc, a.Movement.Speed * Time.deltaTime);
  392.                     standRayDir = (standHit.point - (a.transform.position + standOffset)).normalized;
  393.                     standRay = new Ray(a.transform.position + standOffset, standRayDir);
  394.                 }
  395.  
  396.                 float gravityAmount = Vector3.Dot(a.rb.velocity, a.gravity.Down);
  397.                 a.rb.velocity -= a.gravity.Down * gravityAmount;
  398.             }
  399.             if(a.debugLineColor.a > 0) {
  400.                 NS.Lines.Make(ref a.line_dir,
  401.                               a.transform.position + standOffset,
  402.                               a.transform.position + standRayDir * maxStandHeight + standOffset,
  403.                               a.debugLineColor, IsStanding?0.125f:.25f);
  404.             }
  405.         }
  406.     }
  407.     public Standing stand = new Standing { maxStandHeight = 0.75f, minStandHeight = 0.7f, standRadius = 0.5f, maxStandAngle = 45 };
  408.  
  409.     [System.Serializable]
  410.     public struct Jumping {
  411.         public float minJumpHeight, maxJumpHeight;
  412.         [Tooltip("How long the jump button must be pressed to jump the maximum height")]
  413.         public float fullJumpPressDuration;
  414.         [Tooltip("for double-jumping, put a 1 here. To eliminate jumping, put a 0 here.")]
  415.         public int maxJumps;
  416.         /// <summary>Whether or not the jumper wants to press jump (specifically, how many seconds of jump)</summary>
  417.         [HideInInspector]
  418.         public float PressJump;
  419.         private float currentJumpVelocity, heightReached, heightReachedTotal, timeHeld, targetHeight;
  420.         private bool impulseActive, peaked;
  421.         public bool airImpulseAllowed;
  422.  
  423.         public int JumpsSoFar { get; private set; }
  424.         /// <returns>if this instance is trying to jump</returns>
  425.         public bool IsJumping { get { return PressJump > 0; } set { PressJump = value?Time.deltaTime:0; } }
  426.         public void Init(){
  427.             peaked = false;
  428.         }
  429.         /// <summary>pretends to hold the jump button for the specified duration</summary>
  430.         public void FixedUpdate(RBAgent p) {
  431.             bool _isJumping;
  432.             if(_isJumping = (PressJump > 0)) { PressJump -= Time.deltaTime; }
  433.             if(impulseActive && !_isJumping) { impulseActive = false; }
  434.             if(!_isJumping) { return; }
  435.             // check stable footing for the jump
  436.             if(p.stand.IsStanding) {
  437.                 JumpsSoFar = 0;
  438.                 heightReached = 0;
  439.                 currentJumpVelocity = 0;
  440.                 timeHeld = 0;
  441.             }
  442.             // calculate the jump
  443.             float gForce = p.gravity.Force * p.rb.mass;
  444.             Vector3 jump_force = Vector3.zero, jumpDirection = -p.gravity.Down;
  445.             // if the user wants to jump, and is allowed to jump again
  446.             if(!impulseActive && (JumpsSoFar < maxJumps)) {
  447.                 heightReached = 0;
  448.                 timeHeld = 0;
  449.                 JumpsSoFar++;
  450.                 targetHeight = minJumpHeight * p.rb.mass;
  451.                 float velocityRequiredToJump = Mathf.Sqrt(targetHeight * 2 * gForce);
  452.                 // cancel out other current jump/fall forces
  453.                 float motionInVerticalDirection = Vector3.Dot(jumpDirection, p.rb.velocity);
  454.                 jump_force -= (motionInVerticalDirection * jumpDirection) / Time.deltaTime;
  455.                 // apply proper jump force
  456.                 currentJumpVelocity = velocityRequiredToJump;
  457.                 peaked = false;
  458.                 jump_force += (jumpDirection * currentJumpVelocity) / Time.deltaTime;
  459.                 impulseActive = true;
  460.             } else
  461.                 // if a jump is happening      
  462.                 if(currentJumpVelocity > 0) {
  463.                 // handle jump height: the longer you hold jump, the higher you jump
  464.                 if(_isJumping) {
  465.                     timeHeld += Time.deltaTime;
  466.                     if(timeHeld >= fullJumpPressDuration) {
  467.                         targetHeight = maxJumpHeight;
  468.                         timeHeld = fullJumpPressDuration;
  469.                     } else {
  470.                         targetHeight = minJumpHeight + ((maxJumpHeight - minJumpHeight) * timeHeld / fullJumpPressDuration);
  471.                         targetHeight *= p.rb.mass;
  472.                     }
  473.                     if(heightReached < targetHeight) {
  474.                         float requiredJumpVelocity = Mathf.Sqrt((targetHeight - heightReached) * 2 * gForce);
  475.                         float forceNeeded = requiredJumpVelocity - currentJumpVelocity;
  476.                         jump_force += (jumpDirection * forceNeeded) / Time.deltaTime;
  477.                         currentJumpVelocity = requiredJumpVelocity;
  478.                     }
  479.                 }
  480.             } else {
  481.                 impulseActive = false;
  482.             }
  483.             if(currentJumpVelocity > 0) {
  484.                 float moved = currentJumpVelocity * Time.deltaTime;
  485.                 heightReached += moved;
  486.                 heightReachedTotal += moved;
  487.                 currentJumpVelocity -= gForce * Time.deltaTime;
  488.             } else if(!peaked && !p.stand.IsStanding) {
  489.                 peaked = true;
  490.                 impulseActive = false;
  491.             }
  492.             p.rb.AddForce(jump_force);
  493.         }
  494.     }
  495.     public Jumping jump = new Jumping { minJumpHeight = 0.25f, maxJumpHeight = 2, fullJumpPressDuration = 0.5f, maxJumps = 1};
  496.  
  497.     [Tooltip("if clear, will not draw debug lines")]
  498.     public Color debugLineColor = Color.red;
  499.     private Rigidbody rb;
  500.     private GameObject line_target, line_dir;
  501.     private bool shouldRotateBodyToMatchEyes;
  502.  
  503.     public Vector3 GetMoveForward() {
  504.         return cameraControls.eyes != null ? cameraControls.simpleForward : transform.forward;
  505.     }
  506.  
  507.     private void Awake() {
  508.         rb = GetComponent<Rigidbody>();
  509.         rb.freezeRotation = true;
  510.         rb.useGravity = false;
  511.         aiMovement.RandomWalk.QueueUpdate();
  512.         cameraControls.Init(transform);
  513.     }
  514.  
  515.     public void PickANewTarget() {
  516.         Vector3 direction = Random.onUnitSphere;
  517.         if(!gravity.IgnoreGravityPull) {
  518.             direction = direction.ProjectOntoPlane(gravity.Down);
  519.             direction.Normalize();
  520.         }
  521.         aiMovement.targetLocation = transform.position + direction * Movement.Speed * aiMovement.RandomWalk.Duration;
  522.         if(debugLineColor.a > 0) {
  523.             NS.Lines.MakeCircle(ref line_target, aiMovement.targetLocation, gravity.Down, debugLineColor);
  524.         }
  525.     }
  526.  
  527.     private void FixedUpdate() {
  528.         stand.FixedUpdate(this);
  529.         gravity.Calculate(this, stand.IsStanding);
  530.         jump.FixedUpdate(this);
  531.     }
  532.  
  533.     //private void LateUpdate() { cameraControls.LateUpdate(this); }
  534.     void Update () {
  535.         if(cameraControls.cam != null) {
  536.             bool canMove = stand.IsWalkable || jump.airImpulseAllowed;
  537.             if(canMove) {
  538.                 float gravityAmount = (!gravity.IgnoreGravityPull)?Vector3.Dot(rb.velocity, gravity.Down):0;
  539.                 Movement.Direction = cameraControls.GetDirectionBasedOnInput(this);
  540.                 if(Movement.Direction != Vector3.zero) { shouldRotateBodyToMatchEyes = true; }
  541.                 rb.velocity = Movement.Direction * Movement.Speed + gravity.Down * gravityAmount;
  542.             }
  543.             cameraControls.SetEyeDirectionbasedOnInput(this);
  544.             cameraControls.ZoomBasedOnInput(this);
  545.             if(debugLineColor.a > 0) {
  546.                 NS.Lines.MakeCircle(ref line_target, transform.position, cameraControls.eyes.forward, debugLineColor);
  547.             }
  548.             if(Input.GetButton("Jump")) {
  549.                 jump.PressJump = Time.deltaTime;
  550.             }
  551.         }
  552.         if(cameraControls.clickToMove != CameraControls.MouseClick.none) { // TODO move to FixedUpdate?
  553.             cameraControls.ClickToMove(this);
  554.         }
  555.         if(aiMovement.RandomWalk.Enabled) { // TODO move to FixedUpdate?
  556.             aiMovement.RandomWalk.Update(PickANewTarget);
  557.         }
  558.         if(aiMovement.moveToTarget) { // TODO move to FixedUpdate?
  559.             float gravityAmount = (!gravity.IgnoreGravityPull) ? Vector3.Dot(rb.velocity, gravity.Down) : 0;
  560.             Vector3 dir = aiMovement.GetDirectionTowardTarget(this);
  561.             if(dir != Vector3.zero) {
  562.                 rb.velocity = dir * Movement.Speed + gravity.Down * gravityAmount;
  563.             }
  564.             if(debugLineColor.a > 0) {
  565.                 NS.Lines.MakeArrow(ref line_dir, transform.position, transform.position + dir, debugLineColor);
  566.             }
  567.         } else if(cameraControls.eyes != null) {
  568.             shouldRotateBodyToMatchEyes = cameraControls.RotateBodyToMatchEyes(this, shouldRotateBodyToMatchEyes);
  569.         }
  570.     }
  571. }
  572.  
  573. public class RBAgentCamera : MonoBehaviour {
  574.     public Transform target;
  575.     public float distance = 10;
  576.     //private float actualDistance;
  577.     private Vector3 offset;
  578.     //public bool followRotation = true; // behind-shoulder-3rd-person (true) vs overhead-god-view-follow (false)
  579.     public bool boundToTargetDirection = true;
  580.  
  581.     public void Start() {
  582.         offset = new Vector3(0, 0, -distance);
  583.     }
  584.  
  585.     [HideInInspector]
  586.     /// if set to <c>true</c>, use the player's look rotation
  587.     public bool playerTurningCamera;
  588.     public void LateUpdate() {
  589.         if (target == null) return;
  590.         if(!boundToTargetDirection && !playerTurningCamera) {
  591.             target.rotation = transform.rotation;
  592.         }
  593.         transform.rotation = target.rotation;
  594.         RaycastHit rh = new RaycastHit();
  595.         if (Physics.Raycast(target.position, -target.forward, out rh, distance)) {
  596.             offset = target.forward * -rh.distance;
  597.         } else {
  598.             offset = target.forward * -distance;
  599.         }
  600.         transform.position = target.position + offset;
  601.     }
  602. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement