restructure script folder
This commit is contained in:
@@ -0,0 +1,167 @@
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using TMPro;
|
||||
using Unity.VectorGraphics;
|
||||
using UnityEngine;
|
||||
using UnityEngine.SceneManagement;
|
||||
using UnityEngine.UI;
|
||||
|
||||
public class GameManager : MonoBehaviour
|
||||
{
|
||||
public static GameManager Instance { get; private set; }
|
||||
public DialogueManager DialogueManager { get; private set; }
|
||||
public Inventory Inventory { get; private set; }
|
||||
public Storybools Storybools { get; private set; }
|
||||
|
||||
// Are we currently in a scene transition?
|
||||
private bool isTransitioningScenes = false;
|
||||
private Image blackScreen;
|
||||
private PlayerController playerController;
|
||||
|
||||
private void Awake()
|
||||
{
|
||||
// If there is an instance, and it's not me, delete myself.
|
||||
|
||||
if (Instance != null && Instance != this)
|
||||
{
|
||||
Destroy(this.gameObject);
|
||||
}
|
||||
else
|
||||
{
|
||||
Instance = this;
|
||||
}
|
||||
|
||||
DontDestroyOnLoad(gameObject);
|
||||
|
||||
ReloadReferences();
|
||||
|
||||
SaveSystem.Load();
|
||||
SaveSystem.Save(); // save off any corruption fixes
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Grab everything the GameManager needs to keep track of
|
||||
/// </summary>
|
||||
private void ReloadReferences()
|
||||
{
|
||||
Instance.blackScreen = GameObject.FindWithTag("BlackScreen").GetComponent<Image>();
|
||||
Instance.playerController = GameObject.FindWithTag("Player").GetComponent<PlayerController>();
|
||||
Instance.DialogueManager = GetComponent<DialogueManager>();
|
||||
Instance.DialogueManager.ReloadReferences();
|
||||
|
||||
Instance.Inventory = GetComponent<Inventory>();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Triggers transition to specified scene at the door with the specified ID
|
||||
/// </summary>
|
||||
public void EnterSceneDoor(string scene, int door)
|
||||
{
|
||||
StartCoroutine(EnterSceneDoorCoroutine(scene, door));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Executes transition to specified scene at the door with the specified ID
|
||||
/// </summary>
|
||||
private IEnumerator EnterSceneDoorCoroutine(string scene, int doorId)
|
||||
{
|
||||
Instance.isTransitioningScenes = true;
|
||||
Instance.playerController.SetCharacterControl(false);
|
||||
|
||||
// Fade to black
|
||||
float fadeDuration = 0.2f; // how long to fade to/from black
|
||||
float moveDuration = 0.4f; // how long to auto walk into room from the door
|
||||
float fadeTime = 0;
|
||||
Color blackScreenColor = Color.black;
|
||||
|
||||
while (fadeTime < fadeDuration)
|
||||
{
|
||||
blackScreenColor.a = Mathf.Lerp(0, 1, fadeTime / fadeDuration);
|
||||
blackScreen.color = blackScreenColor;
|
||||
fadeTime += Time.deltaTime;
|
||||
yield return null;
|
||||
}
|
||||
fadeTime = 0;
|
||||
|
||||
|
||||
AsyncOperation asyncLoad = SceneManager.LoadSceneAsync(scene);
|
||||
while (!asyncLoad.isDone)
|
||||
{
|
||||
// Optional: Update a loading bar with asyncLoad.progress
|
||||
yield return null;
|
||||
}
|
||||
|
||||
ReloadReferences();
|
||||
|
||||
// Make sure screen is black in new scene
|
||||
blackScreen.color = blackScreenColor;
|
||||
|
||||
SceneDoor door = GameSceneManager.Instance.GetDoorWithId(doorId);
|
||||
|
||||
if (Instance.playerController != null && GameSceneManager.Instance != null)
|
||||
{
|
||||
if (door != null)
|
||||
{
|
||||
Instance.playerController.CharacterControllerMove(door.gameObject.transform.position - playerController.transform.position);
|
||||
Instance.playerController.DougBody.transform.rotation = door.gameObject.transform.rotation;
|
||||
}
|
||||
}
|
||||
|
||||
// Fade back in
|
||||
while (fadeTime < fadeDuration)
|
||||
{
|
||||
blackScreenColor.a = Mathf.Lerp(1, 0, fadeTime / fadeDuration);
|
||||
Instance.blackScreen.color = blackScreenColor;
|
||||
fadeTime += Time.deltaTime;
|
||||
|
||||
Instance.playerController.WalkInDirection((door.WalkDirection.position - playerController.transform.position).normalized);
|
||||
yield return null;
|
||||
}
|
||||
|
||||
// move character a little more
|
||||
while (fadeTime < moveDuration)
|
||||
{
|
||||
Instance.playerController.WalkInDirection((door.WalkDirection.position - playerController.transform.position).normalized);
|
||||
fadeTime += Time.deltaTime;
|
||||
yield return null;
|
||||
}
|
||||
|
||||
fadeTime = 0;
|
||||
|
||||
Instance.isTransitioningScenes = false;
|
||||
Instance.playerController.SetCharacterControl(true);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Are we currently in the middle of a scene transition?
|
||||
/// </summary>
|
||||
public bool InSceneTransition()
|
||||
{
|
||||
return Instance.isTransitioningScenes;
|
||||
}
|
||||
|
||||
#region Storybool Save/Load
|
||||
public void SaveStoryBools(ref StoryboolSaveData data)
|
||||
{
|
||||
data.Storybools = Instance.Storybools;
|
||||
}
|
||||
|
||||
public void LoadStoryBools(StoryboolSaveData data)
|
||||
{
|
||||
if (data.Storybools != null)
|
||||
{
|
||||
Instance.Storybools = data.Storybools;
|
||||
}
|
||||
else
|
||||
{
|
||||
Instance.Storybools = new Storybools();
|
||||
}
|
||||
}
|
||||
#endregion
|
||||
}
|
||||
|
||||
[System.Serializable]
|
||||
public struct StoryboolSaveData
|
||||
{
|
||||
public Storybools Storybools;
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 65dc1a5d5b17b874087eb45227f838f2
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: -1
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,32 @@
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
|
||||
// Manages scene-specific info, WILL be destroyed on load, and there is one of these
|
||||
// in each scene
|
||||
public class GameSceneManager : MonoBehaviour
|
||||
{
|
||||
public static GameSceneManager Instance { get; private set; }
|
||||
|
||||
// This is a list of doors that take us to different scenes. We'll use this
|
||||
// to tell the GameManager which door to put us at when we enter a new scene.
|
||||
public List<SceneDoor> SceneDoors;
|
||||
|
||||
public SceneDoor GetDoorWithId(int id)
|
||||
{
|
||||
return SceneDoors.Find(x => x.DoorId == id);
|
||||
}
|
||||
|
||||
private void Awake()
|
||||
{
|
||||
// If there is an instance, and it's not me, delete myself.
|
||||
|
||||
if (Instance != null && Instance != this)
|
||||
{
|
||||
Destroy(this);
|
||||
}
|
||||
else
|
||||
{
|
||||
Instance = this;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,2 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 53b8d8c9181974149990f96ea419a6c1
|
||||
@@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 9c62a4e46b92717449db7214fd217c32
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,65 @@
|
||||
using UnityEngine;
|
||||
|
||||
public class Quest : MonoBehaviour
|
||||
{
|
||||
public bool hasStarted = false;
|
||||
public bool hasCompleted = false;
|
||||
|
||||
public string[] askText; // ask the player to complete the task
|
||||
public string[] duringText; // what to say to the player when the task is complete
|
||||
public string[] completionText; // what to say to the player upon completion
|
||||
|
||||
public int questID = 0; // connects the quest to the registry, which gives us conditions
|
||||
|
||||
public void Start()
|
||||
{
|
||||
// check if we've completed the quest
|
||||
hasCompleted = QuestRegistry.Instance.CompletedQuests.Contains(questID);
|
||||
hasStarted = QuestRegistry.Instance.ActiveQuests.Contains(questID);
|
||||
|
||||
// this shouldn't be possible, but if the save is changed manually it could happen
|
||||
if (hasStarted && hasCompleted)
|
||||
{
|
||||
hasStarted = false;
|
||||
|
||||
// make sure only one reference exists
|
||||
QuestRegistry.Instance.CompletedQuests.RemoveAll(id => id == questID);
|
||||
QuestRegistry.Instance.CompletedQuests.Add(questID);
|
||||
|
||||
QuestRegistry.Instance.ActiveQuests.RemoveAll(id => id == questID);
|
||||
SaveSystem.Save();
|
||||
}
|
||||
}
|
||||
|
||||
public void StartQuest()
|
||||
{
|
||||
hasStarted = true;
|
||||
QuestRegistry.Instance.ActiveQuests.Add(questID);
|
||||
SaveSystem.Save();
|
||||
}
|
||||
|
||||
public bool CheckComplete()
|
||||
{
|
||||
QuestBool[] conditionList = QuestRegistry.Instance.QuestBoolMap[questID];
|
||||
|
||||
if (conditionList != null)
|
||||
{
|
||||
foreach (QuestBool condition in conditionList)
|
||||
{
|
||||
// try each condition until we hit a false
|
||||
if (!condition.getValue())
|
||||
return false;
|
||||
}
|
||||
|
||||
// otherwise return true and mark quest complete
|
||||
QuestRegistry.Instance.ActiveQuests.Remove(questID);
|
||||
QuestRegistry.Instance.CompletedQuests.Add(questID);
|
||||
|
||||
SaveSystem.Save();
|
||||
hasCompleted = true;
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,2 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 2db38219bed101e44b995a3611e4cedd
|
||||
@@ -0,0 +1,106 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using UnityEngine;
|
||||
|
||||
public class QuestRegistry : MonoBehaviour
|
||||
{
|
||||
// This will keep a register of all quest data and status
|
||||
public static QuestRegistry Instance { get; private set; }
|
||||
public Dictionary<int, QuestBool[]> QuestBoolMap;
|
||||
public List<int> CompletedQuests;
|
||||
public List<int> ActiveQuests;
|
||||
|
||||
private void Awake()
|
||||
{
|
||||
// If there is an instance, and it's not me, delete myself.
|
||||
|
||||
if (Instance != null && Instance != this)
|
||||
{
|
||||
Destroy(this);
|
||||
}
|
||||
else
|
||||
{
|
||||
Instance = this;
|
||||
Instance.QuestBoolMap = PopulateQuestData();
|
||||
|
||||
PopulateQuestData();
|
||||
DontDestroyOnLoad(gameObject);
|
||||
}
|
||||
}
|
||||
|
||||
private Dictionary<int, QuestBool[]> PopulateQuestData()
|
||||
{
|
||||
Dictionary<int, QuestBool[]> questBoolMap = new Dictionary<int, QuestBool[]>();
|
||||
|
||||
// Quest Bool Structure: QID<QuestID>_<Bool Number>_<descriptiveName>
|
||||
// Example: QID11_4_landBurgerGreaseCleared
|
||||
#region 1 - Sam's Plea
|
||||
QuestBool[] QID1_List = new QuestBool[2];
|
||||
|
||||
// QID1_1_hasEnoughStarshards
|
||||
QID1_List[0] = new QuestBool(() =>
|
||||
{
|
||||
return GameManager.Instance.Inventory.GetItemQuantity(ItemIdEnum.STAR_SHARD) > 2;
|
||||
});
|
||||
|
||||
// QID1_2_hasHelpedSam
|
||||
QID1_List[1] = new QuestBool(() =>
|
||||
{
|
||||
return GameManager.Instance.Storybools.hasHelpedSam;
|
||||
});
|
||||
|
||||
questBoolMap.Add(1, QID1_List);
|
||||
#endregion
|
||||
|
||||
return questBoolMap;
|
||||
}
|
||||
|
||||
// Save completed quests to disk
|
||||
public void SaveQuestData(ref QuestSaveData data)
|
||||
{
|
||||
data.ActiveQuests = Instance.ActiveQuests;
|
||||
data.CompletedQuests = Instance.CompletedQuests;
|
||||
}
|
||||
|
||||
public void LoadQuestData(QuestSaveData data)
|
||||
{
|
||||
if (data.ActiveQuests != null)
|
||||
{
|
||||
Instance.ActiveQuests = data.ActiveQuests;
|
||||
}
|
||||
else
|
||||
{
|
||||
Instance.ActiveQuests = new List<int>();
|
||||
}
|
||||
|
||||
if (data.CompletedQuests != null)
|
||||
{
|
||||
Instance.CompletedQuests = data.CompletedQuests;
|
||||
}
|
||||
else
|
||||
{
|
||||
Instance.CompletedQuests = new List<int>();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public class QuestBool
|
||||
{
|
||||
// This let's us define complex behavior for quests. We can also store
|
||||
// raw booleans for this if we have story beats we want to keep track of.
|
||||
public Func<bool> getValue;
|
||||
|
||||
public QuestBool(Func<bool> getValue)
|
||||
{
|
||||
this.getValue = getValue;
|
||||
}
|
||||
}
|
||||
|
||||
[System.Serializable]
|
||||
public struct QuestSaveData
|
||||
{
|
||||
public List<int> CompletedQuests;
|
||||
public List<int> ActiveQuests;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: cf9658f7202522245b3ac80235b98b50
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: -2
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,10 @@
|
||||
using UnityEngine;
|
||||
|
||||
[System.Serializable]
|
||||
public class Storybools
|
||||
{
|
||||
// not sure how we'll organize this yet, but right now lets do it by quest
|
||||
#region QID1
|
||||
public bool hasHelpedSam = false;
|
||||
#endregion
|
||||
}
|
||||
@@ -0,0 +1,2 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 70e96df6062507943b1f7ae7df89dee5
|
||||
@@ -0,0 +1,86 @@
|
||||
using System;
|
||||
using System.IO;
|
||||
using UnityEngine;
|
||||
|
||||
public class SaveSystem
|
||||
{
|
||||
private static SaveData _saveData = new SaveData();
|
||||
|
||||
[System.Serializable]
|
||||
public struct SaveData
|
||||
{
|
||||
public QuestSaveData QuestData;
|
||||
public StoryboolSaveData StoryboolData;
|
||||
public InventorySaveData InventorySaveData;
|
||||
}
|
||||
|
||||
public static string SaveFileName()
|
||||
{
|
||||
return Application.persistentDataPath + "/save.data";
|
||||
}
|
||||
|
||||
public static void GenerateCorruptedSaveReadme()
|
||||
{
|
||||
string path = Application.persistentDataPath + "/README.txt";
|
||||
string errorText = "Your save was corrupted.\n\n" +
|
||||
"This can happen when you edit the save manually, or if the game closed while saving. Your\n" +
|
||||
"corrupted save file has been saved in this directory as 'save.data.backup' if you'd like to\n" +
|
||||
"try manually fixing it. It should follow standard JSON formatting.\n\n" +
|
||||
"Once you fix it, just delete the current save.data file, and remove the '.backup' from your \n" +
|
||||
"old save file. Good luck, and sorry for the inconvenience!";
|
||||
|
||||
File.WriteAllText(path, errorText);
|
||||
}
|
||||
|
||||
public static void Save()
|
||||
{
|
||||
HandleSaveData();
|
||||
|
||||
File.WriteAllText(SaveFileName(), JsonUtility.ToJson(_saveData, true));
|
||||
}
|
||||
|
||||
private static void HandleSaveData()
|
||||
{
|
||||
GameManager.Instance.SaveStoryBools(ref _saveData.StoryboolData);
|
||||
GameManager.Instance.Inventory.SaveInventory(ref _saveData.InventorySaveData);
|
||||
QuestRegistry.Instance.SaveQuestData(ref _saveData.QuestData);
|
||||
}
|
||||
|
||||
public static void Load()
|
||||
{
|
||||
string saveContent;
|
||||
|
||||
try
|
||||
{
|
||||
saveContent = File.ReadAllText(SaveFileName());
|
||||
}
|
||||
catch (FileNotFoundException)
|
||||
{
|
||||
Save(); // create new save file if one does not exist
|
||||
saveContent = File.ReadAllText(SaveFileName());
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
_saveData = JsonUtility.FromJson<SaveData>(saveContent);
|
||||
}
|
||||
catch (ArgumentException)
|
||||
{
|
||||
// Likely a JSON parse error. Let's back up the old version of the save and
|
||||
// make a new one for now
|
||||
|
||||
File.WriteAllText(SaveFileName() + ".backup", saveContent);
|
||||
GenerateCorruptedSaveReadme();
|
||||
Save();
|
||||
}
|
||||
|
||||
HandleLoadData();
|
||||
}
|
||||
|
||||
public static void HandleLoadData()
|
||||
{
|
||||
GameManager.Instance.LoadStoryBools(_saveData.StoryboolData);
|
||||
GameManager.Instance.Inventory.LoadInventory(_saveData.InventorySaveData);
|
||||
QuestRegistry.Instance.LoadQuestData(_saveData.QuestData);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,2 @@
|
||||
fileFormatVersion: 2
|
||||
guid: e2f06729fcc0a08408d90d49c2336d22
|
||||
@@ -0,0 +1,78 @@
|
||||
using System.Collections;
|
||||
using UnityEngine;
|
||||
using UnityEngine.Rendering.Universal;
|
||||
using UnityEngine.UI;
|
||||
|
||||
// Handle room and scene transitions
|
||||
public class TeleportHandler : MonoBehaviour
|
||||
{
|
||||
public Image blackScreenObject;
|
||||
PlayerController playerController;
|
||||
|
||||
private void Start()
|
||||
{
|
||||
playerController = GetComponent<PlayerController>();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Triggers the room entrance coroutine, only works if the character is not controllable (keeps from double transitioning)
|
||||
/// </summary>
|
||||
public void EnterRoom(RoomDoor door)
|
||||
{
|
||||
if (playerController.GetCharacterHasControl())
|
||||
StartCoroutine(EnterRoomCoroutine(door));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Handle teleportation and timing for entering rooms within a scene
|
||||
/// </summary>
|
||||
IEnumerator EnterRoomCoroutine(RoomDoor door)
|
||||
{
|
||||
float fadeDuration = 0.2f; // how long to fade to/from black
|
||||
float moveDuration = 0.4f; // how long to auto walk into room from the door
|
||||
float fadeTime = 0;
|
||||
Color blackScreenColor = Color.black;
|
||||
|
||||
playerController.SetCharacterControl(false);
|
||||
|
||||
// Play door open animation
|
||||
if (door.requiresInteraction)
|
||||
yield return new WaitForSeconds(0.2f);
|
||||
|
||||
while (fadeTime < fadeDuration)
|
||||
{
|
||||
blackScreenColor.a = Mathf.Lerp(0, 1, fadeTime / fadeDuration);
|
||||
blackScreenObject.color = blackScreenColor;
|
||||
fadeTime += Time.deltaTime;
|
||||
yield return null;
|
||||
}
|
||||
fadeTime = 0;
|
||||
|
||||
playerController.CharacterControllerMove(door.linkedDoor.transform.position - transform.position);
|
||||
playerController.DougBody.transform.rotation = door.linkedDoor.transform.rotation;
|
||||
|
||||
while (fadeTime < fadeDuration)
|
||||
{
|
||||
blackScreenColor.a = Mathf.Lerp(1, 0, fadeTime / fadeDuration);
|
||||
blackScreenObject.color = blackScreenColor;
|
||||
playerController.WalkInDirection((door.linkedDoor.WalkDirection.position - playerController.transform.position).normalized);
|
||||
|
||||
fadeTime += Time.deltaTime;
|
||||
yield return null;
|
||||
}
|
||||
// move character a little more
|
||||
while (fadeTime < moveDuration)
|
||||
{
|
||||
playerController.WalkInDirection((door.linkedDoor.WalkDirection.position - playerController.transform.position).normalized);
|
||||
fadeTime += Time.deltaTime;
|
||||
yield return null;
|
||||
}
|
||||
fadeTime = 0;
|
||||
|
||||
// Play exit animation for linked door (if it exists)
|
||||
door.linkedDoor.CloseDoor();
|
||||
yield return new WaitForSeconds(0.2f);
|
||||
playerController.SetCharacterControl(true);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,2 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 4e4075a1c9b67af429062d6dffd07682
|
||||
Reference in New Issue
Block a user