Dungeon Escape
Dungeon Escape is a narration based adventure game developed for a 48-hour game jam using Unity. I have synchronized the narration with the player's actions.
Code Snippets
Narrator Manager
public class NarratorManager : MonoBehaviour
{
public static NarratorManager Instance { get; private set; }
[SerializeField] private AudioSource audioSource;
[Header("First Level")] [SerializeField]
private GameObject deadDwarf;
[SerializeField] private GameObject dwarfBracelet;
[SerializeField] private GameObject lockedDoor;
[Header("Second Level")] public bool HasDiedOnTheSecondLevel = false;
[SerializeField] private PlayerMovement playerMovement;
[Header("Third Level")] [SerializeField]
private float thirdLevelSecondsUntilTimeStop;
[SerializeField] private Rigidbody rb;
[SerializeField] private GameObject correctLever;
//[SerializeField] private bool correctLeverPulled;
[SerializeField] private GameObject thirdLevelTeleporter;
[Header("Fourth Level")] [SerializeField]
private GameObject lavaToDisable;
[SerializeField] private GameObject grapplingHookUI;
[SerializeField] private GameObject theEndText;
private Coroutine currentRoutine = null;
[SerializeField] private SerializedDictionary<AudioType, AudioClip> clipsDic;
private void Awake()
{
if (Instance != null && Instance != this)
Destroy(this);
else
Instance = this;
}
private void Start()
{
Teleporter.OnTeleported += NarrateLevels;
deadDwarf.GetComponent<DeadBody>().OnBraceletPickedUp += StartNarratingFirstLevelPartTwo;
lockedDoor.GetComponent<CageDoor>().OnDoorOpened += StartNarratingFirstLevelPartThree;
currentRoutine = StartCoroutine(NarrateFirstLevelNoBracelet());
playerMovement.canWallRun = false;
}
private IEnumerator NarrateFirstLevelNoBracelet()
{
audioSource.clip = clipsDic[AudioType.Intro];
audioSource.Play();
yield return new WaitWhile(() => audioSource.isPlaying);
deadDwarf.layer = LayerMask.NameToLayer("Interactable");
}
private void StartNarratingFirstLevelPartTwo(object sender, EventArgs e)
{
StartCoroutine(NarrateFirstLevelGotBracelet());
}
private void StartNarratingFirstLevelPartThree(object sender, EventArgs e)
{
StartCoroutine(NarrateFirstLevelDoorOpened());
}
private IEnumerator NarrateFirstLevelGotBracelet()
{
audioSource.clip = clipsDic[AudioType.Intro2];
audioSource.Play();
yield return new WaitWhile(() => audioSource.isPlaying);
lockedDoor.layer = LayerMask.NameToLayer("Interactable");
}
private IEnumerator NarrateFirstLevelDoorOpened() // Edge case: Player speedruns to level 2
{
audioSource.clip = clipsDic[AudioType.Parkour];
audioSource.Play();
yield return new WaitWhile(() => audioSource.isPlaying);
}
private void NarrateLevels(object sender, TeleportEventArgs e)
{
switch (e.NewLevel)
{
case 1:
StartCoroutine(NarrateSecondLevel());
break;
case 2:
StartCoroutine(NarrateThirdLevel());
break;
case 3:
lavaToDisable.SetActive(false);
break;
}
}
private IEnumerator NarrateSecondLevel()
{
// Disable wall jump!
audioSource.clip = clipsDic[AudioType.Parkour2];
audioSource.Play();
SubtitleManager.OnSubtitle?.Invoke();
yield return new WaitWhile(() => audioSource.isPlaying);
while (true)
{
if (HasDiedOnTheSecondLevel)
{
yield return NarrateSecondLevelFirstDeath();
yield break;
}
yield return null;
}
}
private IEnumerator NarrateSecondLevelFirstDeath()
{
audioSource.clip = clipsDic[AudioType.Parkour2Second];
audioSource.Play();
SubtitleManager.OnSubtitle?.Invoke();
playerMovement.canWallRun = true;
yield return new WaitWhile(() => audioSource.isPlaying);
audioSource.clip = clipsDic[AudioType.MomAreYouStillPlaying];
audioSource.Play();
SubtitleManager.OnSubtitle?.Invoke();
yield return new WaitWhile(() => audioSource.isPlaying);
audioSource.clip = clipsDic[AudioType.Parkour2Third];
audioSource.Play();
SubtitleManager.OnSubtitle?.Invoke();
}
private IEnumerator NarrateThirdLevel()
{
audioSource.clip = clipsDic[AudioType.Puzzle];
audioSource.Play();
SubtitleManager.OnSubtitle?.Invoke();
yield return new WaitWhile(() => audioSource.isPlaying);
//yield return new WaitForSeconds(thirdLevelSecondsUntilTimeStop);
}
public void DoNarrateThirdLevelDeath()
{
StartCoroutine(NarrateThirdLevelDeath());
}
private IEnumerator NarrateThirdLevelDeath()
{
audioSource.Stop();
//subtitle stoplayacagız.
rb.constraints = RigidbodyConstraints.FreezeAll;
Time.timeScale = 0f;
// ---------------------------------------Freeze player HERE!---------------------------------------
audioSource.clip = clipsDic[AudioType.PuzzleSecond];
audioSource.Play();
SubtitleManager.OnSubtitle?.Invoke();
yield return new WaitWhile(() => audioSource.isPlaying);
correctLever.SetActive(true);
Time.timeScale = 1f;
rb.constraints = RigidbodyConstraints.FreezeRotation;
Destroy(lavaToDisable.GetComponent<Animator>());
lavaToDisable.transform.localScale = new Vector3(0.2f, 1.5f, 0.2f);
// Make lava smaller
}
public void DoNarrateCorrectLevelPulledThirdLevel()
{
Debug.Log("Lever pulled!");
StartCoroutine(NarrateCorrectLevelPulledThirdLevel());
}
private IEnumerator NarrateCorrectLevelPulledThirdLevel()
{
Debug.Log("BRUH");
thirdLevelTeleporter.SetActive(true);
yield return new WaitForSeconds(0.75f);
yield return NarrateFourthLevel();
thirdLevelTeleporter.SetActive(false);
}
private IEnumerator NarrateFourthLevel()
{
audioSource.clip = clipsDic[AudioType.Parkour3AfterLevelFinish];
audioSource.Play();
SubtitleManager.OnSubtitle?.Invoke();
yield return new WaitForSeconds(25f);
grapplingHookUI.SetActive(true);
yield return new WaitUntil(() => Input.GetKeyDown(KeyCode.C));
grapplingHookUI.SetActive(false);
//yield return new WaitWhile(() => audioSource.isPlaying);
}
public void DoNarrateCoinsCollectedFirstTimeFourthLevel()
{
StartCoroutine(NarrateCoinsCollectedFirstTimeFourthLevel());
}
public void DoNarrateCoinsCollectedNotFirstTimeFourthLevel()
{
StartCoroutine(NarrateCoinsCollectedNotFirstTimeFourthLevel());
}
public void DoNarrateCoinsNotCollectedFourthLevel()
{
StartCoroutine(NarrateCoinsNotCollectedFourthLevel());
}
private IEnumerator NarrateCoinsCollectedFirstTimeFourthLevel()
{
audioSource.clip = clipsDic[AudioType.EndCoinsCollectedFirstTime];
audioSource.Play();
yield return new WaitWhile(() => audioSource.isPlaying);
yield return NarrateMomTalkFourthLevel();
}
private IEnumerator NarrateCoinsCollectedNotFirstTimeFourthLevel()
{
audioSource.clip = clipsDic[AudioType.EndCoinsCollectedNotFirstTime];
audioSource.Play();
yield return new WaitWhile(() => audioSource.isPlaying);
yield return NarrateMomTalkFourthLevel();
}
private IEnumerator NarrateCoinsNotCollectedFourthLevel()
{
audioSource.clip = clipsDic[AudioType.EndCoinsNotCollectedAtAll];
audioSource.Play();
yield return new WaitWhile(() => audioSource.isPlaying);
}
private IEnumerator NarrateMomTalkFourthLevel()
{
audioSource.clip = clipsDic[AudioType.MomGoToSleep];
audioSource.Play();
yield return new WaitWhile(() => audioSource.isPlaying);
audioSource.clip = clipsDic[AudioType.OkayMom];
audioSource.Play();
yield return new WaitWhile(() => audioSource.isPlaying);
theEndText.SetActive(true);
}
}
public enum AudioType
{
Intro,
Intro2,
Parkour,
Parkour2,
Parkour2Second,
Parkour2Third,
Parkour3AfterLevelFinish,
Puzzle,
PuzzleSecond,
EndCoinsCollectedFirstTime,
EndCoinsCollectedNotFirstTime,
EndCoinsNotCollectedAtAll,
MomAreYouStillPlaying,
MomGoToSleep,
OkayMom
}