using System.Collections; using System.Collections.Generic; using UnityEngine; public class DumbEnemyHoverMovement : 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 maxRNGThrust; public float movementDecayRate; private List _movementMoveTimers = new List(); public float patternChangeInterval; private TimerHelper _movementPatternTimer; private float _currentHoldHeight; private float _heightChangeTick; public float heightChangeInterval; private int _currentPattern; private int _nextThrustDir; private int _nextTurnDir; protected override void DoAwakeTasks() { base.DoAwakeTasks(); } // Start is called before the first frame update private 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; _currentHoldHeight = GetCurrentHeight(); _heightChangeTick = 0.0f; _movementPatternTimer = new TimerHelper(patternChangeInterval, false); _movementPatternTimer.HasTicked(patternChangeInterval + 100.0f); _currentPattern = Random.Range(0, 4); BaseOnStart(); // Custom start stuff can go here } private void DoAIPhysics(float currentTimeStep) { } /// /// 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. private 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.up); Vector3 myLocation = Vector3.ProjectOnPlane(transform.position, Vector3.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 (_movementPatternTimer.HasTicked(currentTimeStep)) { _currentPattern = Random.Range(0, 4); _movementMoveTimers.Clear(); switch (_currentPattern) { default: case 0: int dirRandom = Random.Range(0, 2); if (dirRandom == 0) { _nextTurnDir = -1; } else { _nextTurnDir = 1; } _movementMoveTimers.Add(new TimerHelper(30.0f, false)); _movementMoveTimers.Add(new TimerHelper(3.0f, false)); break; case 1: _movementMoveTimers.Add(new TimerHelper(10.0f)); break; case 2: int zigRandom = Random.Range(0, 2); if (zigRandom == 0) { _nextTurnDir = -1; } else { _nextTurnDir = 1; } _movementMoveTimers.Add(new TimerHelper(3.0f, false)); break; case 3: _movementMoveTimers.Add(new TimerHelper(15.0f, false)); break; } _movementPatternTimer.RestartTimer(); } else { switch (_currentPattern) { default: case 0: _aiVert = 1.0f; if (_movementMoveTimers[0].HasTicked(currentTimeStep)) { if (_movementMoveTimers[1].HasTicked(currentTimeStep)) { int dirRandom = Random.Range(0, 2); if (dirRandom == 0) { _nextTurnDir = -1; } else { _nextTurnDir = 1; } _movementMoveTimers[0].RestartTimer(); _movementMoveTimers[1].RestartTimer(); } else { _aiHorz = _nextTurnDir; } } else { _aiHorz = 0.0f; } break; case 1: _aiVert = 1.0f; if (_movementMoveTimers[0].HasTicked(currentTimeStep)) { int dirTimesRan = _movementMoveTimers[0].TimesRun % 2; if (dirTimesRan == 0) { _aiHorz = 1; } else { _aiHorz = -1; } } break; case 2: _aiVert = 1.0f; if (_movementMoveTimers[0].HasTicked(currentTimeStep)) { _nextTurnDir *= -1; _movementMoveTimers[0].RestartTimer(); } else { _aiHorz = _nextTurnDir; } break; case 3: if (_movementMoveTimers[0].HasTicked(currentTimeStep)) { _nextThrustDir = Random.Range(0, 2); _nextTurnDir = Random.Range(-1, 2); _movementMoveTimers[0].RestartTimer(); } else { _aiVert = _nextThrustDir; _aiHorz = _nextTurnDir; } break; } } if (_currentHoldHeight >= 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.0f * _aiVert; 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.0f * _aiVert; } } else { if (_residualThrust > 0.0f) { if (_residualThrustCurrentTime >= residualThrustTimeTickMax) { _residualThrust -= residualThrustIdleDecayRate; } _thrustDirection = _residualThrust / residualThrustMax; } else { _thrusting = false; _thrustDirection = 0.0f; } } // 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 (_heightChangeTick >= heightChangeInterval) { _currentHoldHeight = Random.Range(startHeight, startHeight + 5.0f); _heightChangeTick = 0.0f; } else { _heightChangeTick += 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); } } } }