using UnityEngine; public class ChaserEnemyHoverMovement : HoverMovement { // Game object to track the player GO private GameObject _player; private GameObject _blackHole; private EnemyColliderManager _enemyColliderManager; // Residual Thrust variables to handle the "glide" after the gameObject has moved public float residualThrustStep; public float residualThrustMax; public float residualThrustTimeTickMax; public float residualThrustDecayRate; public float residualThrustIdleDecayRate; public float jumpForce; public float jumpMaxTime; private float _residualThrust; private float _residualThrustCurrentTime; private float _currentJumpTime; private bool _isJumping; // Variables for RNG movement private float _aiVert; private float _aiHorz; private bool _aiJump; public float chargePower; public float chargeCooldown; public float chargeCooldownSpeed; private bool _charged; private float _currentChargeCooldownTick; protected override void DoAwakeTasks() { base.DoAwakeTasks(); } // Start is called before the first frame update void Start() { // We have to find the player since setting it in the editor doesnt work correctly _player = GameObject.Find("Player"); _blackHole = GameObject.Find("BlackHole"); _enemyColliderManager = gameObject.GetComponent(); _residualThrust = 0.0f; _residualThrustCurrentTime = 0.0f; _currentJumpTime = 0.0f; _isJumping = false; _aiJump = false; _aiHorz = 0.0f; _aiVert = 0.0f; _charged = false; _currentChargeCooldownTick = 0.0f; BaseOnStart(); // Custom start stuff can go here } void DoAIPhysics(float currentTimeStep) { RaycastHit belowCheck; Physics.SphereCast(transform.position, 2.0f, -transform.up, out belowCheck, 5.0f, LayerMask.GetMask("Player")); if (belowCheck.rigidbody != null) { if (!_charged) { float playerHeight = _player.GetComponent().GetCurrentHeight(); if (playerHeight + 1.0f < GetCurrentHeight()) { _objectRigidbody.AddRelativeForce(Vector3.down * chargePower, ForceMode.Impulse); _charged = true; } } } } /// /// Calculates some RNG movement for the attached Enemy. /// /// The time unit currently used, typically deltatime or deltafixed time depending on if its the fixed update or not. void DoAI(float currentTimeStep) { if (_enemyColliderManager.Magnetized) { _noMovement = true; } else { _noMovement = false; } // Get the Up vector of each gameObject so we can compare its X values rather than the Y Vector3 playerDirection = _player.transform.position - transform.position; Vector3 playerLocation = Vector3.ProjectOnPlane(_player.transform.position, Vector3.forward); Vector3 myLocation = Vector3.ProjectOnPlane(transform.position, Vector3.forward); Vector3 direction = playerLocation - myLocation; float angleDiff = Mathf.Atan2(direction.y, direction.x) * Mathf.Rad2Deg; float facingPlayer = Vector3.Dot(playerDirection.normalized, transform.forward); // Added a check to see if the difference is big enough to warrant a turn otherwise they just get stuck turning forever float playerHeight = _player.GetComponent().GetCurrentHeight(); _aiVert = 1; if (facingPlayer > 0.8f) { _aiHorz = 0.0f; if (playerDirection.magnitude <= 10.0f) { if (!_charged) { if (playerHeight + 1.5f > GetCurrentHeight()) { _aiJump = false; } else { _aiJump = true; } } } else { if (playerHeight > GetCurrentHeight()) { _aiJump = true; } } } else { _aiHorz = angleDiff; if ((playerHeight - 0.5f) >= GetCurrentHeight()) { RaycastHit aboveCheck; Physics.SphereCast(transform.position, 3.0f, transform.up, out aboveCheck, 5.0f, LayerMask.GetMask("Player")); if (aboveCheck.rigidbody != null) { if (GetCurrentHeight() < playerHeight) { _objectRigidbody.velocity = Vector3.zero; _aiJump = false; } else { _aiJump = true; } } else { _aiJump = true; } } else { _aiJump = false; } } } /// /// Processes the inputs needed to move the gameObject, the turn direction, thrust direction and any residual thrust calculations so that we dont just stop in place. /// Anything in this method can be removed, as long as the _turnDirection and _thrustDirection are set then the parent script with handle the orbit and positioning. /// /// The time unit currently used, typically deltatime or deltafixed time depending on if its the fixed update or not. protected override void ProcessPreMovement(float currentTimeStep) { // Check if movement has been frozen if (!freezeMovement) { // Get the Horz and Vert axis from the RNG (or whatever vars you want) float horzInput = _aiHorz; float vertInput = _aiVert; // Check horz direction value, pos = Right, neg = Left if (horzInput > 0) { _turnDirection = 1; } else if (horzInput < 0) { _turnDirection = -1; } else { _turnDirection = 0; } // Check if the vert is pushed forwards or back, pos = forward, neg = back if (vertInput > 0) { _thrusting = true; _thrustDirection = 1; if (_residualThrust < residualThrustMax) { _residualThrust += residualThrustStep * currentTimeStep; } } // If the Enemy is holding backwards else if (vertInput < 0) { if (_residualThrust > 0.0f) { if (_residualThrustCurrentTime >= residualThrustTimeTickMax) { _residualThrust -= residualThrustDecayRate; } _thrustDirection = _residualThrust / residualThrustMax; } else { _thrusting = true; _thrustDirection = -1; } } else { if (_residualThrust > 0.0f) { if (_residualThrustCurrentTime >= residualThrustTimeTickMax) { _residualThrust -= residualThrustIdleDecayRate; } _thrustDirection = _residualThrust / residualThrustMax; } else { _thrusting = false; _thrustDirection = 0; } } // Clamp the residual thrust so we cant fall below 0 or greater than the max value set _residualThrust = Mathf.Clamp(_residualThrust, 0, residualThrustMax); if (_residualThrustCurrentTime >= residualThrustTimeTickMax) { _residualThrustCurrentTime = 0.0f; } else { _residualThrustCurrentTime += currentTimeStep; } // Check if the jump button if (_aiJump && !_isJumping) { _isJumping = true; } // Run any base class stuff base.ProcessPreMovement(currentTimeStep); } } /// /// Method for dealing with the jump physics, this should be in the fixed update since it uses rigidbody physics /// private void ProcessJump() { // If the enemy is jumping add the jump force if (_isJumping) { _objectRigidbody.AddRelativeForce(Vector3.up * jumpForce * Time.fixedDeltaTime, ForceMode.Impulse); if (_currentJumpTime >= jumpMaxTime) { _currentJumpTime = 0.0f; _isJumping = false; _aiJump = false; } else { _currentJumpTime += Time.fixedDeltaTime; } } } private void ProcessCooldowns(float currentTimeStep) { if (_charged) { if (_currentChargeCooldownTick >= chargeCooldown) { _charged = false; _currentChargeCooldownTick = 0.0f; } else { _currentChargeCooldownTick += currentTimeStep; } } } private void FixedUpdate() { if (!GameEngine.isPaused) { if (objectIsActive) { DoAIPhysics(Time.fixedDeltaTime); ProcessJump(); } } } // Update is called once per frame void Update() { if (!GameEngine.isPaused) { if (objectIsActive) { ProcessWorkingStartValues(Time.deltaTime); DoAI(Time.deltaTime); ProcessPreMovement(Time.deltaTime); ProcessCurrentMovement(Time.deltaTime); ProcessPostMovement(); ProcessCooldowns(Time.deltaTime); } } } }