Files
blackhole-escape/Assets/Scripts/Scripts/BasicFollowEnemyHoverMovement.cs
iDunnoDev 0360907df1 Added Main menu Changes to UI
Added Rules Menu Changes to UI
Added Cutscenes to the rules scene
Reorganised Files
2022-06-22 13:30:58 +01:00

328 lines
11 KiB
C#

using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
/// <summary>
/// Class for dealing with a basic follow enemy AI
/// </summary>
public class BasicFollowEnemyHoverMovement : HoverMovement
{
// Game object to track the player GO
private GameObject _player;
private GameObject _blackHole;
// 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 chargeRadius;
public float chargePower;
public float chargeCooldown;
private bool _charged;
private float _currentChargeCooldownTick;
private RaycastHit _rayHitPosition;
public 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");
_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)
{
if (_rayHitPosition.rigidbody != null)
{
if (_rayHitPosition.rigidbody.CompareTag("Player") && _rayHitPosition.distance <= 5.0f)
{
if (!_charged)
{
float playerHeight = _player.GetComponent<PlayerHoverMovement>().GetCurrentHeight();
if (playerHeight < GetCurrentHeight())
{
_objectRigidbody.AddRelativeForce((Vector3.forward + Vector3.down) * chargePower);
_charged = true;
}
}
}
}
}
/// <summary>
/// Calculates some RNG movement for the attached Enemy.
/// </summary>
/// <param name="currentTimeStep">The time unit currently used, typically deltatime or deltafixed time depending on if its the fixed update or not.</param>
void DoAI(float currentTimeStep)
{
// 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);
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<PlayerHoverMovement>().GetCurrentHeight();
Physics.SphereCast(transform.position, chargeRadius, transform.forward, out _rayHitPosition);
_aiVert = 1;
if (facingPlayer > 0.8f)
{
_aiHorz = 0.0f;
if (_rayHitPosition.rigidbody != null)
{
if (_rayHitPosition.rigidbody.CompareTag("Player") && _rayHitPosition.distance <= 15.0f)
{
if (!_charged)
{
if (playerHeight > GetCurrentHeight())
{
_objectRigidbody.velocity = Vector3.zero;
_aiJump = false;
}
else
{
_aiVert = 0.5f;
_aiJump = true;
}
}
}
else
{
if (playerHeight > GetCurrentHeight())
{
_aiJump = true;
}
}
}
}
else
{
_aiHorz = angleDiff;
if (((playerHeight - 0.5f) >= GetCurrentHeight()))
{
if (_rayHitPosition.rigidbody != null)
{
if (_rayHitPosition.rigidbody.CompareTag("Player") && (GetCurrentHeight() < playerHeight))
{
Debug.LogError("PLAYER ABOVE DONT JUMP (plz)");
_objectRigidbody.velocity = Vector3.zero;
_aiJump = false;
}
else
{
_aiJump = true;
}
}
else
{
_aiJump = true;
}
}
else
{
_aiJump = false;
}
}
}
/// <summary>
/// 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.
/// </summary>
/// <param name="currentTimeStep">The time unit currently used, typically deltatime or deltafixed time depending on if its the fixed update or not.</param>
public 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);
}
}
/// <summary>
/// Method for dealing with the jump physics, this should be in the fixed update since it uses rigidbody physics
/// </summary>
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;
}
}
}
void ProcessCooldowns(float currentTimeStep)
{
if (_charged)
{
if (_currentChargeCooldownTick >= chargeCooldown)
{
_charged = false;
_currentChargeCooldownTick = 0.0f;
}
else
{
_currentChargeCooldownTick += currentTimeStep;
}
}
}
private void FixedUpdate()
{
if (objectIsActive)
{
DoAIPhysics(Time.fixedDeltaTime);
ProcessJump();
}
}
// Update is called once per frame
void Update()
{
if (objectIsActive)
{
DoAI(Time.deltaTime);
ProcessPreMovement(Time.deltaTime);
ProcessCurrentMovement(Time.deltaTime);
ProcessPostMovement();
ProcessCooldowns(Time.deltaTime);
}
}
}