environment management

This commit is contained in:
2023-05-15 14:04:09 +02:00
parent fd705d46e8
commit d486a1cf6e
58 changed files with 674 additions and 435 deletions

View File

@@ -1,5 +1,6 @@
using System.Collections.Generic;
using System.Linq;
using EscapeRoomEngine.Engine.Runtime.Environment;
using EscapeRoomEngine.Engine.Runtime.Measurements;
using EscapeRoomEngine.Engine.Runtime.Modules;
using EscapeRoomEngine.Engine.Runtime.Modules.Description;
@@ -48,6 +49,7 @@ namespace EscapeRoomEngine.Engine.Runtime
private readonly List<Room> _rooms = new();
private List<PuzzleModuleDescription> _availablePuzzles, _plannedPuzzles;
private List<RoomEnvironment> _availableEnvironments;
private GameObject _playSpaceOrigin;
private void Awake()
@@ -58,6 +60,7 @@ namespace EscapeRoomEngine.Engine.Runtime
_availablePuzzles = new List<PuzzleModuleDescription>(theme.puzzleTypes);
_plannedPuzzles = new List<PuzzleModuleDescription>(_availablePuzzles);
ResetAvailableEnvironments();
}
private void Start()
@@ -67,6 +70,11 @@ namespace EscapeRoomEngine.Engine.Runtime
_playSpaceOrigin.transform.localPosition = new Vector3(-GameControl.Instance.RoomSize.x / 2f, 0, -GameControl.Instance.RoomSize.y / 2f);
}
private void ResetAvailableEnvironments()
{
_availableEnvironments = new List<RoomEnvironment>(theme.environments);
}
#region Generation
public void GenerateRoom()
@@ -75,10 +83,23 @@ namespace EscapeRoomEngine.Engine.Runtime
var intro = NumberOfRooms == 0;
// get the last entrance from the newest room or create a spawn passage with no entrance door for where the player will start
var entrance = intro ? new Passage(new DoorModule(null, theme.spawnDoor)) : _rooms.Last().exit;
var room = new Room(entrance);
Passage entrance;
RoomEnvironment environment;
if (intro)
{
entrance = new Passage(new DoorModule(null, theme.spawnDoor));
environment = theme.intro.introEnvironment;
}
else
{
entrance = _rooms.Last().exit;
if (_availableEnvironments.Count == 0)
{
ResetAvailableEnvironments();
}
environment = _availableEnvironments.PopRandomElement();
}
var room = new Room(entrance, environment);
_rooms.Add(room);
if (intro)
@@ -98,15 +119,11 @@ namespace EscapeRoomEngine.Engine.Runtime
var roomId = _rooms.Count - 1;
room.InstantiateRoom(_playSpaceOrigin.transform, roomId * roomOffset, roomId.ToString());
Instantiate(room.environment.environment, room.roomObject.transform, false);
if (intro)
{
Instantiate(theme.intro, room.roomObject.transform, false);
FindObjectOfType<Intro>().Place(room.exit.fromOut.DoorState.transform);
}
else if (theme.environment)
{
Instantiate(theme.environment, room.roomObject.transform, false);
}
GameControl.Instance.TimeInRoom = 0;
UpdateUI();

View File

@@ -1,4 +1,5 @@
using System.Collections.Generic;
using EscapeRoomEngine.Engine.Runtime.Environment;
using EscapeRoomEngine.Engine.Runtime.Modules.Description;
using EscapeRoomEngine.Engine.Runtime.Utilities;
using JetBrains.Annotations;
@@ -23,8 +24,8 @@ namespace EscapeRoomEngine.Engine.Runtime
public SpaceTile spaceTile;
[BoxGroup("Theme")]
[Tooltip("The environment that is placed around every generated room.")]
public GameObject environment;
[Tooltip("The environments that are placed around generated rooms.")]
public List<RoomEnvironment> environments;
[BoxGroup("Theme")]
public DynamicColor puzzleColor, solvedColor, activeColor;

View File

@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: f07b7a9e0ae34430999958d61ecc7e2c
timeCreated: 1684146335

View File

@@ -0,0 +1,85 @@
using System;
using System.Collections;
using NaughtyAttributes;
using UnityEngine;
namespace EscapeRoomEngine.Engine.Runtime.Environment
{
[RequireComponent(typeof(AudioSource))]
public class AmbienceAudio : MonoBehaviour
{
public static AmbienceAudio Instance { get; private set; }
public float fadeDuration = 0.5f;
public AmbienceClip initialAmbience;
[BoxGroup("Internal")] [SerializeField] private AudioSource[] sources;
private AudioSource CurrentSource => sources[currentSource];
private AudioSource OtherSource => sources[(currentSource + 1) % 2];
private int currentSource;
private readonly Coroutine[] _activeFades = new Coroutine[2]; // the indices in these fades do not necessarily correspond to the sources
private void Awake()
{
Instance = this;
if (sources.Length != 2)
{
throw new Exception("There must be two sources.");
}
if (CurrentSource == OtherSource)
{
throw new Exception("Current source must be different from other source.");
}
foreach (var source in sources)
{
source.loop = true;
}
}
public void StartAmbience()
{
CrossFadeTo(initialAmbience);
}
public void CrossFadeTo(AmbienceClip ambience)
{
// prepare fade source
var fadeSource = OtherSource;
fadeSource.clip = ambience.audio;
fadeSource.Play();
// stop any running fades
foreach (var fade in _activeFades)
{
if (fade != null)
{
StopCoroutine(fade);
}
}
// start new fades
_activeFades[0] = StartCoroutine(Fade(CurrentSource, CurrentSource.volume, 0));
_activeFades[1] = StartCoroutine(Fade(fadeSource, fadeSource.volume, ambience.volume));
// switch current source
currentSource = (currentSource + 1) % 2;
}
private IEnumerator Fade(AudioSource source, float from, float to)
{
var startTime = Time.time;
while (Math.Abs(source.volume - to) > 0.0001f)
{
source.volume = Mathf.Clamp01(Mathf.Lerp(
from,
to,
(Time.time - startTime) / fadeDuration));
yield return null;
}
}
}
}

View File

@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: affaa904605c46dca7162e99fd363b5a
timeCreated: 1684143627

View File

@@ -0,0 +1,12 @@
using NaughtyAttributes;
using UnityEngine;
namespace EscapeRoomEngine.Engine.Runtime.Environment
{
[CreateAssetMenu(menuName = "Environment/Ambience Clip")]
public class AmbienceClip : ScriptableObject
{
[Required] public AudioClip audio;
public float volume = 1;
}
}

View File

@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: 3d36d46846cd41019647bae00e4b0f17
timeCreated: 1684145618

View File

@@ -0,0 +1,12 @@
using NaughtyAttributes;
using UnityEngine;
namespace EscapeRoomEngine.Engine.Runtime.Environment
{
[CreateAssetMenu(menuName = "Environment/Room", order = 0)]
public class RoomEnvironment : ScriptableObject
{
[Required] public AmbienceClip ambience;
[Required] public GameObject environment;
}
}

View File

@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: 3b7d4fea984e4fff841ac107b6896270
timeCreated: 1684146291

View File

@@ -1,11 +1,14 @@
using NaughtyAttributes;
using EscapeRoomEngine.Engine.Runtime.Environment;
using NaughtyAttributes;
using UnityEngine;
using UnityEngine.Serialization;
namespace EscapeRoomEngine.Engine.Runtime
{
public class Intro : MonoBehaviour
{
[BoxGroup("Internal")] [SerializeField] private AudioSource _sphereAudio;
public RoomEnvironment introEnvironment;
[FormerlySerializedAs("_sphereAudio")] [BoxGroup("Internal")] [SerializeField] private AudioSource sphereAudio;
public void Place(Transform placement)
{
@@ -16,7 +19,7 @@ namespace EscapeRoomEngine.Engine.Runtime
public void StartTalking()
{
_sphereAudio.Play();
sphereAudio.Play();
}
}
}

View File

@@ -1,5 +1,6 @@
using System.Collections.Generic;
using System.Linq;
using EscapeRoomEngine.Engine.Runtime.Environment;
using EscapeRoomEngine.Engine.Runtime.Measurements;
using EscapeRoomEngine.Engine.Runtime.Modules;
using EscapeRoomEngine.Engine.Runtime.Modules.Description;
@@ -16,6 +17,7 @@ namespace EscapeRoomEngine.Engine.Runtime
public class Room
{
internal Passage entrance, exit;
internal RoomEnvironment environment;
internal GameObject roomObject;
internal readonly List<PuzzleModule> puzzles = new();
@@ -26,10 +28,12 @@ namespace EscapeRoomEngine.Engine.Runtime
private readonly List<Space> _spaces = new();
private readonly List<DoorModule> _doors = new();
private bool startedMeasuring;
internal Room(Passage entrance)
internal Room(Passage entrance, RoomEnvironment environment)
{
this.entrance = entrance;
this.environment = environment;
}
internal void AddSpace(Space space, Passage spaceExit)
@@ -84,20 +88,29 @@ namespace EscapeRoomEngine.Engine.Runtime
// ReSharper disable once SwitchStatementMissingSomeEnumCasesNoDefault
switch (type)
{
// generate a new room as soon as the player completes all puzzles in this one
// generate a new room as soon as the player completes all puzzles in this room
case DoorEventType.Unlocked when !LastRoom && door.Equals(exit.fromOut):
Engine.Instance.GenerateRoom();
break;
// start measurements on every puzzle as soon as the player enters the last room
case DoorEventType.ExitedFrom when door.Equals(entrance.toIn) && Engine.Instance.CurrentRoom.Contains(this):
puzzles.ForEach(puzzle => Measure.StartMeasuring((PuzzleModuleDescription)puzzle.description));
// start measurements on every puzzle as soon as the player enters this room the first time
if (!startedMeasuring)
{
startedMeasuring = true;
puzzles.ForEach(puzzle => Measure.StartMeasuring((PuzzleModuleDescription)puzzle.description));
}
// hide the intro room
if (Engine.Instance.NumberOfRooms == 2)
{
// hide the intro room when exiting the first portal
Engine.Instance.HidePreviousRoom(false);
}
break;
}
if (type == DoorEventType.ExitedFrom)
{
AmbienceAudio.Instance.CrossFadeTo(environment.ambience);
}
};
}

View File

@@ -1,4 +1,5 @@
using System.Collections.Generic;
using EscapeRoomEngine.Engine.Runtime.Environment;
using EscapeRoomEngine.Engine.Runtime.Measurements;
using EscapeRoomEngine.Engine.Runtime.Modules.Description;
using EscapeRoomEngine.Engine.Runtime.Utilities;
@@ -129,6 +130,7 @@ namespace EscapeRoomEngine.Engine.Runtime.UI
public void StartGame()
{
gameState = GameState.Running;
AmbienceAudio.Instance.StartAmbience();
PauseGame(); // the time is not running during the intro
TimeElapsed = 0;