environment management
This commit is contained in:
@@ -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();
|
||||
|
||||
@@ -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;
|
||||
|
||||
3
Assets/Engine/Runtime/Environment.meta
Normal file
3
Assets/Engine/Runtime/Environment.meta
Normal file
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: f07b7a9e0ae34430999958d61ecc7e2c
|
||||
timeCreated: 1684146335
|
||||
85
Assets/Engine/Runtime/Environment/AmbienceAudio.cs
Normal file
85
Assets/Engine/Runtime/Environment/AmbienceAudio.cs
Normal 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;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
3
Assets/Engine/Runtime/Environment/AmbienceAudio.cs.meta
Normal file
3
Assets/Engine/Runtime/Environment/AmbienceAudio.cs.meta
Normal file
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: affaa904605c46dca7162e99fd363b5a
|
||||
timeCreated: 1684143627
|
||||
12
Assets/Engine/Runtime/Environment/AmbienceClip.cs
Normal file
12
Assets/Engine/Runtime/Environment/AmbienceClip.cs
Normal 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;
|
||||
}
|
||||
}
|
||||
3
Assets/Engine/Runtime/Environment/AmbienceClip.cs.meta
Normal file
3
Assets/Engine/Runtime/Environment/AmbienceClip.cs.meta
Normal file
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 3d36d46846cd41019647bae00e4b0f17
|
||||
timeCreated: 1684145618
|
||||
12
Assets/Engine/Runtime/Environment/RoomEnvironment.cs
Normal file
12
Assets/Engine/Runtime/Environment/RoomEnvironment.cs
Normal 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;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 3b7d4fea984e4fff841ac107b6896270
|
||||
timeCreated: 1684146291
|
||||
@@ -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();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
@@ -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;
|
||||
|
||||
Reference in New Issue
Block a user