Diegetic Interface Script
using UnityEngine;
//using UnityEngine.UIElements;
using UnityEngine.UI;
public class UIRoomScript : MonoBehaviour, IRoomUI
{
[SerializeField]
int roomNumber;
[SerializeField]
bool isGreen;
Image imageRef;
void Awake()
{
CacheImage();
}
// Start is called once before the first execution of Update after the MonoBehaviour is created
void Start()
{
CacheImage();
if (imageRef != null) imageRef.enabled = false;
}
// Update is called once per frame
void Update()
{
}
void IRoomUI.GoVisible(int roomID, bool green)
{
CacheImage();
if (imageRef == null) return;
if (roomNumber == roomID && isGreen == green)
{
imageRef.enabled = true;
}
}
void IRoomUI.GoInvisible(int roomID, bool green)
{
CacheImage();
if (imageRef == null) return;
if (roomNumber == roomID && isGreen == green)
{
imageRef.enabled = false;
}
}
private void CacheImage()
{
if (imageRef == null) imageRef = GetComponentInChildren<Image>();
}
}
Motion Sensor for Diegetic Interface
using System;
using UnityEngine;
public class MovementSensorScript : MonoBehaviour, IMovementSensorInteraction, IEventInteract
{
bool[] roomArray = new bool[4];
public PowerManager powerManager;
int enemyLocation;
int activeRooms = 0;
bool initialUpdate = false;
UIRoomScript[] imageRefs = new UIRoomScript[8];
void Awake()
{
CacheImageRefs();
}
// Start is called once before the first execution of Update after the MonoBehaviour is created
void Start()
{
var enemyRef = GetComponent<EnemyAInew>();
//Initializes array to be false
roomArray[0] = false;
roomArray[1] = false;
roomArray[2] = false;
roomArray[3] = false;
//References to the all of the computer UI scripts
CacheImageRefs();
}
// Update is called once per frame
void Update()
{
//checks validation bounds of the code
var checkIndex = enemyLocation - 1;
if(checkIndex < 0 || checkIndex > roomArray.Length - 1)
{
Debug.Log("Error Index Out of range:" + checkIndex);
return;
}
if (roomArray[checkIndex] == true)
{
// *2) -1 is done as "imageRefs" is an array of 8 however we only want to reference the parts of the array that hold the references to the Red images
// Array is structured as: Green1, Red1, Green2, Red2, Green3, Red3, Green4, Red4
var interfaceMessage = GetRoomUi(enemyLocation, false);
if (interfaceMessage == null) return;
interfaceMessage.GoVisible(enemyLocation, false);
}
else
{
// *2) -1 is done as "imageRefs" is an array of 8 however we only want to reference the parts of the array that hold the references to the Red images
// Array is structured as: Green1, Red1, Green2, Red2, Green3, Red3, Green4, Red4
var interfaceMessage = GetRoomUi(enemyLocation, false);
if (interfaceMessage == null) return;
interfaceMessage.GoInvisible(enemyLocation, false);
}
}
void IMovementSensorInteraction.UpdateEnemyLocation(int newLocation)
{
if (initialUpdate == false)
{
enemyLocation = newLocation;
initialUpdate = true;
}
else
{
var interfaceMessage = GetRoomUi(enemyLocation, false);
if (interfaceMessage != null)
{
interfaceMessage.GoInvisible(enemyLocation, false);
}
enemyLocation = newLocation;
}
}
//Toggle correct boolean in array and run correct powerManager function
void UpdateSensor(int roomToUpdate)
{
int roomIndex = roomToUpdate - 1;
bool sensorIsOn = roomArray[roomIndex];
if (sensorIsOn == false && powerManager.CurrentPower <= 0) return;
//Toggle wether room is active
roomArray[roomIndex] = !sensorIsOn;
if (roomArray[roomIndex] == true)
{
powerManager.RemovePower(1);
activeRooms += 1;
// *2) -2 is done as "imageRefs" is an array of 8 however we only want to reference the parts of the array that hold the references to the Green images
// Array is structured as: Green1, Red1, Green2, Red2, Green3, Red3, Green4, Red4
var interfaceMessage = GetRoomUi(roomToUpdate, true);
if (interfaceMessage != null) interfaceMessage.GoVisible(roomToUpdate, true);
}
else
{
powerManager.AddPower(1);
activeRooms -= 1;
// *2) -2 is done as "imageRefs" is an array of 8 however we only want to reference the parts of the array that hold the references to the Green images
// Array example - Green1, Red1, Green2, Red2, Green3, Red3, Green4, Red4
var interfaceMessage = GetRoomUi(roomToUpdate, true);
if (interfaceMessage != null) interfaceMessage.GoInvisible(roomToUpdate, true);
}
}
//Decide which button has been clicked
void IEventInteract.Interact(GameObject sender, Component clickedComponent)
{
switch (clickedComponent.name)
{
case "R1":
UpdateSensor(1);
break;
case "R2":
UpdateSensor(2);
break;
case "R3":
UpdateSensor(3);
break;
case "R4":
UpdateSensor(4);
break;
}
}
private void CacheImageRefs()
{
if (imageRefs != null && imageRefs.Length > 0 && imageRefs[0] != null) return;
imageRefs = transform.root.GetComponentsInChildren<UIRoomScript>(true);
}
private IRoomUI GetRoomUi(int roomNumber, bool isGreen)
{
CacheImageRefs();
int imageIndex = (roomNumber * 2) - (isGreen ? 2 : 1);
if (imageRefs == null || imageIndex < 0 || imageIndex >= imageRefs.Length) return null;
if (imageRefs[imageIndex] == null) return null;
return imageRefs[imageIndex].GetComponentInParent<IRoomUI>();
}
}
Door Script
using UnityEngine;
public class DoorScript : MonoBehaviour, IEventInteract
{
[SerializeField]
private GameObject door;
private bool isClosed = false;
bool isMoving = false;
[SerializeField]
Vector3 openPosition;
[SerializeField]
Vector3 closedPosition;
[SerializeField]
float moveSpeed;
private bool toOpen = false;
private bool toClose = false;
[SerializeField]
private int doorID;
public bool IsClosed => isClosed;
public bool IsMoving => isMoving;
// Start is called once before the first execution of Update after the MonoBehaviour is created
void Start()
{
}
// Update is called once per frame
void Update()
{
//Loops until "amountMoved" is incremented enough
if (toOpen == true && toClose == false)
{
//Only open until reaching the position specified
if (door.transform.localPosition.y < openPosition.y)
{
door.transform.localPosition = new Vector3(door.transform.localPosition.x, door.transform.localPosition.y + ( moveSpeed * Time.deltaTime), door.transform.localPosition.z);
isMoving = true;
}
else
{
toOpen = false;
isClosed = false;
isMoving = false;
}
}
if (toClose == true && toOpen == false)
{
//Only close until reaching the position specified
if (door.transform.localPosition.y > closedPosition.y)
{
door.transform.localPosition = new Vector3(door.transform.localPosition.x, door.transform.localPosition.y - ( moveSpeed * Time.deltaTime), door.transform.localPosition.z);
isMoving = true;
}
else
{
toClose = false;
isClosed = true;
isMoving= false;
}
}
}
//Door Interact Logic
void IEventInteract.Interact(GameObject player, Component hitChild)
{
if (!isMoving)
{
//cache the component
var powerManager = player.GetComponent<PowerManager>();
if (isClosed == false)
{
if (powerManager.CurrentPower < 2) return;
//removes power
powerManager.RemovePower(2);
//Activates variable for Update()
toClose = true;
return;
}
//adds power
powerManager.AddPower(2);
//Activates variable for Update()
toOpen = true;
}
}
}
Wrote the script for a diegetic interface manager, with interactions between a computer screen and an enemy AI. This interface is player controllable and has multiple states.
Wrote the script for a power management system and implemented it between the different mechanics.
Developed a door class that implements the power management system, and has direct interaction with the enemy AI.
Assisted in the design of the overall system and logic for the enemy AI
View and learn more about this project on GitHub.