scripts: better docs, add rudamentary ai

This commit is contained in:
Mark Joshwel 2024-07-05 17:13:34 +08:00
parent 905acc59ec
commit 93583f2c81
8 changed files with 224 additions and 30 deletions

View file

@ -657,13 +657,13 @@ Transform:
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 705507993}
serializedVersion: 2
m_LocalRotation: {x: 0.7111039, y: 0.10104001, z: -0.50427014, w: 0.47940975}
m_LocalPosition: {x: 2067, y: 670, z: -98}
m_LocalRotation: {x: 0.71824706, y: -0.000055872606, z: -0.56672776, w: 0.40365946}
m_LocalPosition: {x: 1869, y: 670, z: 1020}
m_LocalScale: {x: 1, y: 1, z: 1}
m_ConstrainProportionsScale: 0
m_Children: []
m_Father: {fileID: 0}
m_LocalEulerAnglesHint: {x: 51.603, y: -92.931, z: -146.832}
m_LocalEulerAnglesHint: {x: 35.436, y: -92.234, z: -145.83}
--- !u!114 &705507996
MonoBehaviour:
m_ObjectHideFlags: 0

View file

@ -48,7 +48,7 @@ public class AudioManager : MonoBehaviour
[SerializeField] public AudioClip menuButtonHover;
/// <summary>
/// function to set don't destroy on load and check for multiple instances
/// function to set doesn't destroy on load and checks for multiple instances
/// </summary>
private void Awake()
{
@ -57,7 +57,7 @@ private void Awake()
{
// set this instance as the singleton instance
Instance = this;
// don't destroy this instance on scene load
// don't destroy this instance on a scene load
DontDestroyOnLoad(gameObject);
Debug.Log("AudioManager: Awake as singleton instance");

View file

@ -12,7 +12,7 @@
public class CreditsMenu : CommonMenu
{
/// <summary>
/// button to return to main menu
/// button to return to the main menu
/// </summary>
public Button ButtonReturn;
@ -33,12 +33,12 @@ public override void OnEnable()
}
/// <summary>
/// handles return to main menu button press,
/// handles "return to main menu" button press,
/// signals the game manager appropriately
/// </summary>
private void OptionReturnToMainMenu()
{
// return to main menu
// return to the main menu
Game.SetDisplayState(GameManager.DisplayState.ScreenMainMenu);
}
}

View file

@ -1,7 +1,7 @@
/*
* author: mark joshwel
* date: 29/5/2024
* description: game manager singleton for single source of truth state management
* description: game manager singleton for a single source of truth state management
*/
using UnityEngine;
@ -22,7 +22,7 @@ public enum DisplayState
ScreenOptionsMenu,
ScreenCreditsMenu,
ScreenPauseMenu,
ScreenCaughtPause,
ScreenCaughtMenu,
ScreenEscapedMenu,
UnassociatedState
}
@ -54,7 +54,7 @@ public enum DisplayState
// private Scene _previousScene;
/// <summary>
/// function to set don't destroy on load and check for multiple instances
/// function to set doesn't destroy on load and checks for multiple instances
/// </summary>
private void Awake()
{
@ -63,7 +63,7 @@ private void Awake()
{
// set this instance as the singleton instance
Instance = this;
// don't destroy this instance on scene load
// don't destroy this instance on a scene load
DontDestroyOnLoad(gameObject);
Debug.Log("GameManager: Awake as singleton instance");
@ -79,7 +79,7 @@ private void Awake()
}
/// <summary>
/// called when game starts, sets state to main menu
/// called when the game starts, sets state to the main menu
/// </summary>
// /// <exception cref="Exception">generic exception it couldn't verify a safe state when starting the game</exception>
private void Start()
@ -155,11 +155,6 @@ private void PauseGameHelper(DisplayState incomingState)
var possibleMenuObject = menu.gameObject.GetComponent<CommonMenu>();
if (possibleMenuObject == null) continue;
// Debug.Log(
// $"GameManager: PauseGameHelper - found menu '{menu}' "
// + $"with associated state {associatedState} "
// + $"against incoming state {incomingState}");
// guard clause if the menu isn't what we're looking for
if (possibleMenuObject.associatedState != incomingState)
continue;
@ -230,8 +225,8 @@ public void SetDisplayState(DisplayState displayState)
// set the state of the game to the incoming state
_state = displayState;
// if we're transitioning into gameplay or into the main menu
// we'll need a post step to enable the correct camera
// if we're transitioning into gameplay or into the main menu,
// we'll need a post-step to enable the correct camera
if (displayState is not (DisplayState.Game or DisplayState.ScreenMainMenu))
return;
@ -250,11 +245,11 @@ public void SetDisplayState(DisplayState displayState)
GameObject targetCameraObject;
// switch on the state to enable the correct camera
// could be an if but unity optimises switch statements anyways
// could be an if statement, but unity optimizes switch statements anyway
switch (displayState)
{
// if we're transitioning to the main menu state,
// change camera to the main menu camera under the Menus tagged parent object
// change the camera to the main menu camera under the "Menus"-tagged parent object
case DisplayState.ScreenMainMenu:
Debug.Log("GameManager.SetDisplayState: targeting 'Menu Camera' camera");
targetCameraObject = GameObject.Find("Menu Camera");

View file

@ -0,0 +1,197 @@
/*
* author: mark joshwel
* date: 30/5/2024
* description: enemy AI based off <https://youtu.be/UjkSFoLxesw>
*/
using System;
using UnityEngine;
using UnityEngine.AI;
using Random = UnityEngine.Random;
/// <summary>
/// AI patrolling, chasing and capturing behaviour for the enemy
/// </summary>
public class HerAI : MonoBehaviour
{
/// <summary>
/// variable for the nav mesh agent that determines where the enemy can move
/// </summary>
public NavMeshAgent agent;
/// <summary>
/// variable for the player's position
/// </summary>
public Transform player;
/// <summary>
/// variables to distinguish ground and player for sensing
/// </summary>
public LayerMask whatIsGround, whatIsPlayer;
/// <summary>
/// patrolling: variable for the next point for her to walk to
/// </summary>
public Vector3 walkPoint;
/// <summary>
/// patrolling: variable for the range of the walk point
/// </summary>
public float walkPointRange;
/// <summary>
/// capturing: variable for the time range between captures
/// </summary>
public float timeBetweenCaptures;
/// <summary>
/// variable specifying the sight range of the enemy
/// </summary>
public float sightRange;
/// <summary>
/// variable specifying the attack range of the enemy
/// </summary>
public float attackRange;
/// <summary>
/// boolean variable for the player being in sight range
/// </summary>
public bool playerInSightRange;
/// <summary>
/// boolean variable for the player being in attack range
/// </summary>
public bool playerInCaptureRange;
/// <summary>
/// capturing: variable for if the enemy has attempted to capture the player
/// </summary>
private bool _attemptedCapture;
/// <summary>
/// variable to store game manager
/// </summary>
private GameManager _game;
/// <summary>
/// patrolling: variable to determine if the next point is set
/// </summary>
private bool _walkPointSet;
/// <summary>
/// </summary>
private void Awake()
{
player = GameObject.Find("PlayerObj").transform;
agent = GetComponent<NavMeshAgent>();
}
/// <summary>
/// </summary>
private void Update()
{
//Check for sight and attack range
playerInSightRange = Physics.CheckSphere(transform.position, sightRange, whatIsPlayer);
playerInCaptureRange = Physics.CheckSphere(transform.position, attackRange, whatIsPlayer);
if (!playerInSightRange && !playerInCaptureRange) Patrolling();
if (playerInSightRange && !playerInCaptureRange) ChasePlayer();
if (playerInCaptureRange && playerInSightRange) CapturePlayer();
}
/// <summary>
/// function to find and store the game manager
/// </summary>
/// <exception cref="Exception">generic exception when the object is in an unplayable state</exception>
private void OnEnable()
{
// get the game manager
_game = GameObject.Find("GameManager").GetComponent<GameManager>();
if (_game == null)
throw new Exception("HerAI: could not find GameManager (unreachable?)");
}
// /// <summary>
// /// function to destroy the enemy
// /// </summary>
// private void DestroyEnemy()
// {
// Destroy(gameObject);
// }
/// <summary>
/// function to draw/visualize the sight and attack range of the enemy
/// </summary>
private void OnDrawGizmosSelected()
{
Gizmos.color = Color.red;
Gizmos.DrawWireSphere(transform.position, attackRange);
Gizmos.color = Color.yellow;
Gizmos.DrawWireSphere(transform.position, sightRange);
}
/// <summary>
/// function handling patrolling behaviour
/// </summary>
private void Patrolling()
{
if (!_walkPointSet) SearchWalkPoint();
else agent.SetDestination(walkPoint);
// reached walk point
if ((transform.position - walkPoint).magnitude < 1f)
_walkPointSet = false;
}
/// <summary>
/// function to look for and set the next walk point
/// </summary>
private void SearchWalkPoint()
{
//Calculate random point in range
var randomZ = Random.Range(-walkPointRange, walkPointRange);
var randomX = Random.Range(-walkPointRange, walkPointRange);
walkPoint = new Vector3(transform.position.x + randomX, transform.position.y, transform.position.z + randomZ);
if (Physics.Raycast(walkPoint, -transform.up, 2f, whatIsGround))
_walkPointSet = true;
}
/// <summary>
/// function to chase the player
/// </summary>
private void ChasePlayer()
{
agent.SetDestination(player.position);
}
/// <summary>
/// function that captures the player and signals the game manager appropriately
/// </summary>
private void CapturePlayer()
{
// // don't move the enemy
// agent.SetDestination(transform.position);
// look at me!
transform.LookAt(player);
// are we under cooldown?
if (_attemptedCapture) return;
// signal the game manager to show the 'caught!' menu
_game.SetDisplayState(GameManager.DisplayState.ScreenCaughtMenu);
// set the cooldown
_attemptedCapture = true;
Invoke(nameof(ResetCapture), timeBetweenCaptures);
}
/// <summary>
/// function to reset the capture cooldown, called by <c>Invoke()</c>
/// </summary>
private void ResetCapture()
{
_attemptedCapture = false;
}
}

View file

@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: f7baa34c17324b2e9e2123e5cd3d1f07
timeCreated: 1720167784

View file

@ -13,7 +13,7 @@
public class MainMenu : CommonMenu
{
/// <summary>
/// button to show credits menu
/// button to show the credits menu
/// </summary>
public Button ButtonCredits;
@ -23,7 +23,7 @@ public class MainMenu : CommonMenu
public Button ButtonExit;
/// <summary>
/// button to show options menu
/// button to show the options menu
/// </summary>
public Button ButtonOptions;
@ -79,7 +79,7 @@ private void OptionStartGame()
/// </summary>
private void OptionShowCredits()
{
// show credits menu
// show the credits menu
Game.SetDisplayState(GameManager.DisplayState.ScreenCreditsMenu);
}
@ -89,7 +89,7 @@ private void OptionShowCredits()
/// </summary>
private void OptionShowOptions()
{
// show options menu
// show the option menu
Game.SetDisplayState(GameManager.DisplayState.ScreenOptionsMenu);
}
@ -100,7 +100,6 @@ private void OptionShowOptions()
private void OptionQuitGame()
{
// quit game
// TODO: do we need to integrate this with the game manager?
Debug.Log("MainMenu.OptionQuitGame: quit button pressed");
Game.Quit();
}

View file

@ -12,7 +12,7 @@
public class OptionsMenu : CommonMenu
{
/// <summary>
/// button to return to main menu
/// button to return to the main menu
/// </summary>
public Button ButtonReturn;
@ -57,12 +57,12 @@ public override void OnEnable()
}
/// <summary>
/// handles return to main menu button press,
/// handles return to the main menu button press,
/// signals the game manager appropriately
/// </summary>
private void OptionReturnToMainMenu()
{
// return to main menu
// return to the main menu
Game.SetDisplayState(GameManager.DisplayState.ScreenMainMenu);
}