fixed barks/laments pauses while in conversation
This commit is contained in:
@@ -21,7 +21,7 @@ MonoBehaviour:
|
|||||||
LevelNameToDisplay: Test Hub
|
LevelNameToDisplay: Test Hub
|
||||||
DialogueVariableName:
|
DialogueVariableName:
|
||||||
LoadSceneMode: 0
|
LoadSceneMode: 0
|
||||||
- LevelName: Wasteland
|
- LevelName: Wasteland_Arenas
|
||||||
LevelNameToDisplay: Wasteland
|
LevelNameToDisplay: Wasteland
|
||||||
DialogueVariableName:
|
DialogueVariableName:
|
||||||
LoadSceneMode: 0
|
LoadSceneMode: 0
|
||||||
|
|||||||
@@ -2,11 +2,12 @@ using System.Collections;
|
|||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using PixelCrushers; // For Saver
|
using PixelCrushers; // For Saver
|
||||||
using Sirenix.OdinInspector; // For ReadOnly/Button attributes (Optional: remove if not using Odin)
|
using PixelCrushers.DialogueSystem; // REQUIRED: Added for DialogueManager events
|
||||||
|
using Sirenix.OdinInspector;
|
||||||
using UnityEngine;
|
using UnityEngine;
|
||||||
using Random = UnityEngine.Random;
|
using Random = UnityEngine.Random;
|
||||||
|
|
||||||
namespace Beyond // Ensure this namespace matches your project
|
namespace Beyond
|
||||||
{
|
{
|
||||||
[RequireComponent(typeof(Collider))]
|
[RequireComponent(typeof(Collider))]
|
||||||
public class BarkPlayer : Saver
|
public class BarkPlayer : Saver
|
||||||
@@ -28,6 +29,10 @@ namespace Beyond // Ensure this namespace matches your project
|
|||||||
[Tooltip("Play barks within each entry in a random order (shuffled when the entry starts).")]
|
[Tooltip("Play barks within each entry in a random order (shuffled when the entry starts).")]
|
||||||
public bool shuffleOrder = false;
|
public bool shuffleOrder = false;
|
||||||
|
|
||||||
|
[Header("Dialogue Integration")] // --- NEW SECTION ---
|
||||||
|
[Tooltip("How long to wait after a dialogue ends before resuming barks.")]
|
||||||
|
public float resumeDelayAfterDialogue = 2.0f;
|
||||||
|
|
||||||
[Header("Trigger Settings")]
|
[Header("Trigger Settings")]
|
||||||
[Tooltip("Layers that can activate this bark trigger.")]
|
[Tooltip("Layers that can activate this bark trigger.")]
|
||||||
public LayerMask triggeringLayers;
|
public LayerMask triggeringLayers;
|
||||||
@@ -36,30 +41,30 @@ namespace Beyond // Ensure this namespace matches your project
|
|||||||
[Tooltip("If true, the BarkPlayer will be active automatically when the game starts or when loaded without existing save data for it.")]
|
[Tooltip("If true, the BarkPlayer will be active automatically when the game starts or when loaded without existing save data for it.")]
|
||||||
public bool startAutomaticallyOnLoad = false;
|
public bool startAutomaticallyOnLoad = false;
|
||||||
|
|
||||||
// Runtime state fields remain private but visible for debugging if needed
|
|
||||||
[Header("Runtime State (Read Only)")]
|
[Header("Runtime State (Read Only)")]
|
||||||
[SerializeField, ReadOnly] // Use Sirenix ReadOnly or remove if not using Odin
|
[SerializeField, ReadOnly]
|
||||||
private bool _runtime_IsStarted = false; // Tracks the current operational state
|
private bool _runtime_IsStarted = false;
|
||||||
|
|
||||||
[SerializeField, ReadOnly]
|
[SerializeField, ReadOnly]
|
||||||
private int currentEntryArrayIndex = 0; // Index for barkManagerEntryIndices array
|
private int currentEntryArrayIndex = 0;
|
||||||
|
|
||||||
[SerializeField, ReadOnly]
|
[SerializeField, ReadOnly]
|
||||||
private int nextBarkSequenceIndex = 0; // Index for playbackOrder (within current entry)
|
private int nextBarkSequenceIndex = 0;
|
||||||
|
|
||||||
[SerializeField, ReadOnly]
|
[SerializeField, ReadOnly]
|
||||||
private bool isTriggeringObjectInside = false; // Is a valid object currently inside?
|
private bool isTriggeringObjectInside = false;
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
#region Internal Variables
|
#region Internal Variables
|
||||||
|
|
||||||
private List<int> playbackOrder; // Stores the bark order for the CURRENTLY active entry
|
private List<int> playbackOrder;
|
||||||
private bool isInitialized = false;
|
private bool isInitialized = false;
|
||||||
private Collider triggerCollider;
|
private Collider triggerCollider;
|
||||||
private BarkManager barkManager; // Cached reference
|
private BarkManager barkManager;
|
||||||
private Coroutine currentPlaybackCoroutine = null;
|
private Coroutine currentPlaybackCoroutine = null;
|
||||||
private Transform currentTriggererTransform = null; // Transform of the object inside
|
private Coroutine resumeCoroutine = null; // To track the resume timer
|
||||||
|
private Transform currentTriggererTransform = null;
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
@@ -68,10 +73,10 @@ namespace Beyond // Ensure this namespace matches your project
|
|||||||
[System.Serializable]
|
[System.Serializable]
|
||||||
public class BarkPlayerData
|
public class BarkPlayerData
|
||||||
{
|
{
|
||||||
public bool savedIsStarted; // Tracks the saved state from _runtime_IsStarted
|
public bool savedIsStarted;
|
||||||
public int savedCurrentEntryArrayIndex;
|
public int savedCurrentEntryArrayIndex;
|
||||||
public int savedNextBarkSequenceIndex;
|
public int savedNextBarkSequenceIndex;
|
||||||
public bool wasShuffled; // Tracks shuffle setting at time of save
|
public bool wasShuffled;
|
||||||
}
|
}
|
||||||
private BarkPlayerData m_saveData = new BarkPlayerData();
|
private BarkPlayerData m_saveData = new BarkPlayerData();
|
||||||
|
|
||||||
@@ -87,22 +92,35 @@ namespace Beyond // Ensure this namespace matches your project
|
|||||||
triggerCollider = GetComponent<Collider>();
|
triggerCollider = GetComponent<Collider>();
|
||||||
if (!triggerCollider.isTrigger)
|
if (!triggerCollider.isTrigger)
|
||||||
{
|
{
|
||||||
Debug.LogWarning($"BarkPlayer on {gameObject.name}: Collider was not set to 'Is Trigger'. Forcing it.", this);
|
|
||||||
triggerCollider.isTrigger = true;
|
triggerCollider.isTrigger = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (triggeringLayers.value == 0)
|
if (triggeringLayers.value == 0)
|
||||||
{
|
{
|
||||||
int playerLayer = LayerMask.NameToLayer("Player");
|
triggeringLayers = LayerMask.GetMask("Player");
|
||||||
if (playerLayer != -1)
|
}
|
||||||
{
|
}
|
||||||
triggeringLayers = LayerMask.GetMask("Player");
|
|
||||||
Debug.LogWarning($"BarkPlayer on {gameObject.name}: Triggering Layers not set in inspector, defaulting to 'Player' layer.", this);
|
public override void OnEnable()
|
||||||
}
|
{
|
||||||
else
|
base.OnEnable();
|
||||||
{
|
// Subscribe to global Dialogue System events
|
||||||
Debug.LogError($"BarkPlayer ({gameObject.name}): Triggering Layers is not set in the inspector, and the default 'Player' layer was not found. This trigger will likely not activate.", this);
|
// We use the C# event delegates instead of the component message system for reliability
|
||||||
}
|
if (DialogueManager.instance != null)
|
||||||
|
{
|
||||||
|
DialogueManager.instance.conversationStarted += OnDialogueStarted;
|
||||||
|
DialogueManager.instance.conversationEnded += OnDialogueEnded;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void OnDisable()
|
||||||
|
{
|
||||||
|
base.OnDisable();
|
||||||
|
// Unsubscribe to prevent memory leaks
|
||||||
|
if (DialogueManager.instance != null)
|
||||||
|
{
|
||||||
|
DialogueManager.instance.conversationStarted -= OnDialogueStarted;
|
||||||
|
DialogueManager.instance.conversationEnded -= OnDialogueEnded;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -111,7 +129,6 @@ namespace Beyond // Ensure this namespace matches your project
|
|||||||
barkManager = BarkManager.Instance;
|
barkManager = BarkManager.Instance;
|
||||||
if (barkManager == null)
|
if (barkManager == null)
|
||||||
{
|
{
|
||||||
Debug.LogError($"BarkPlayer ({gameObject.name}): Could not find BarkManager instance! Disabling component.", this);
|
|
||||||
enabled = false;
|
enabled = false;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -120,22 +137,12 @@ namespace Beyond // Ensure this namespace matches your project
|
|||||||
|
|
||||||
if (barkManagerEntryIndices == null || barkManagerEntryIndices.Length == 0)
|
if (barkManagerEntryIndices == null || barkManagerEntryIndices.Length == 0)
|
||||||
{
|
{
|
||||||
Debug.LogWarning($"BarkPlayer ({gameObject.name}): No Bark Manager Entry Indices provided. Disabling.", this);
|
|
||||||
enabled = false;
|
enabled = false;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
for (int i = 0; i < barkManagerEntryIndices.Length; i++)
|
|
||||||
{
|
|
||||||
if (barkManagerEntryIndices[i] < 0 || barkManagerEntryIndices[i] >= barkManager.m_barks.Length)
|
|
||||||
{
|
|
||||||
Debug.LogError($"BarkPlayer ({gameObject.name}): Invalid Bark Manager Entry Index {barkManagerEntryIndices[i]} at array position {i}. Max index is {barkManager.m_barks.Length - 1}. Disabling.", this);
|
|
||||||
enabled = false;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
isInitialized = true;
|
isInitialized = true;
|
||||||
CheckForAutoStartIfInside(); // Check immediately if conditions are met
|
CheckForAutoStartIfInside();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void OnDrawGizmos()
|
private void OnDrawGizmos()
|
||||||
@@ -151,73 +158,91 @@ namespace Beyond // Ensure this namespace matches your project
|
|||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
|
#region Dialogue System Event Handlers (New Logic)
|
||||||
|
|
||||||
|
// Called automatically by Dialogue System whenever ANY conversation starts
|
||||||
|
private void OnDialogueStarted(Transform actor)
|
||||||
|
{
|
||||||
|
if (resumeCoroutine != null) StopCoroutine(resumeCoroutine);
|
||||||
|
|
||||||
|
// Halt the bark loop immediately
|
||||||
|
if (currentPlaybackCoroutine != null)
|
||||||
|
{
|
||||||
|
Debug.Log($"BarkPlayer ({gameObject.name}): Dialogue started. Halting barks.", this);
|
||||||
|
StopCoroutine(currentPlaybackCoroutine);
|
||||||
|
currentPlaybackCoroutine = null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Called automatically by Dialogue System whenever ANY conversation ends
|
||||||
|
private void OnDialogueEnded(Transform actor)
|
||||||
|
{
|
||||||
|
// Don't resume if we aren't supposed to be running or nobody is inside
|
||||||
|
if (_runtime_IsStarted && isTriggeringObjectInside && enabled)
|
||||||
|
{
|
||||||
|
Debug.Log($"BarkPlayer ({gameObject.name}): Dialogue ended. Resuming in {resumeDelayAfterDialogue}s.", this);
|
||||||
|
resumeCoroutine = StartCoroutine(ResumeAfterDialogueDelay());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private IEnumerator ResumeAfterDialogueDelay()
|
||||||
|
{
|
||||||
|
yield return new WaitForSeconds(resumeDelayAfterDialogue);
|
||||||
|
|
||||||
|
// Check conditions again in case player left during the wait
|
||||||
|
CheckForAutoStartIfInside();
|
||||||
|
resumeCoroutine = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
#region Trigger Handling
|
#region Trigger Handling
|
||||||
|
|
||||||
private void OnTriggerEnter(Collider other)
|
private void OnTriggerEnter(Collider other)
|
||||||
{
|
{
|
||||||
// Only ignore if not initialized or component is disabled
|
|
||||||
if (!isInitialized || !enabled) return;
|
if (!isInitialized || !enabled) return;
|
||||||
|
|
||||||
// --- Layer Check ---
|
|
||||||
int otherLayer = other.gameObject.layer;
|
int otherLayer = other.gameObject.layer;
|
||||||
if ((triggeringLayers.value & (1 << otherLayer)) == 0)
|
if ((triggeringLayers.value & (1 << otherLayer)) == 0) return;
|
||||||
{
|
|
||||||
return; // Layer not in mask, ignore this trigger event
|
|
||||||
}
|
|
||||||
|
|
||||||
// --- Check if already processing an object ---
|
if (isTriggeringObjectInside && other.transform != currentTriggererTransform) return;
|
||||||
// This prevents multiple triggering objects from interfering. Only the first one in matters.
|
if (isTriggeringObjectInside) return;
|
||||||
if (isTriggeringObjectInside && other.transform != currentTriggererTransform)
|
|
||||||
|
isTriggeringObjectInside = true;
|
||||||
|
currentTriggererTransform = other.transform;
|
||||||
|
|
||||||
|
// Added check: Don't start barking if a conversation is ALREADY active
|
||||||
|
if (DialogueManager.isConversationActive)
|
||||||
{
|
{
|
||||||
// If another object enters while one is already tracked, ignore the new one.
|
Debug.Log($"BarkPlayer ({gameObject.name}): Trigger entered, but dialogue is active. Waiting for dialogue end.", this);
|
||||||
// If it's the *same* object re-entering (somehow), this check might be too strict,
|
|
||||||
// but standard OnTriggerEnter/Exit should handle one object at a time.
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (isTriggeringObjectInside) return; // Simplified: if already tracking one, ignore others.
|
|
||||||
|
|
||||||
// --- Valid Trigger - Mark presence ---
|
|
||||||
// We set these REGARDLESS of _runtime_IsStarted so state is correct when StartPlayer() is called
|
|
||||||
Debug.Log($"BarkPlayer ({gameObject.name}): Triggering object '{other.name}' entered (tracking presence).", this);
|
|
||||||
isTriggeringObjectInside = true;
|
|
||||||
currentTriggererTransform = other.transform; // Store the transform for barking
|
|
||||||
|
|
||||||
// --- Start Playback Coroutine if player is started and not already running ---
|
|
||||||
// This handles the case where the player enters *after* StartPlayer() has been called
|
|
||||||
if (_runtime_IsStarted && currentPlaybackCoroutine == null)
|
if (_runtime_IsStarted && currentPlaybackCoroutine == null)
|
||||||
{
|
{
|
||||||
Debug.Log($"BarkPlayer ({gameObject.name}): Player is active. Starting playback loop due to new entry.", this);
|
|
||||||
// Apply potentially loaded/saved array index before starting loop
|
|
||||||
currentEntryArrayIndex = Mathf.Clamp(m_saveData.savedCurrentEntryArrayIndex, 0, Mathf.Max(0, barkManagerEntryIndices.Length - 1));
|
currentEntryArrayIndex = Mathf.Clamp(m_saveData.savedCurrentEntryArrayIndex, 0, Mathf.Max(0, barkManagerEntryIndices.Length - 1));
|
||||||
// nextBarkSequenceIndex will be set by PrepareEntrySequence inside the coroutine
|
|
||||||
currentPlaybackCoroutine = StartCoroutine(ContinuousPlaybackLoop());
|
currentPlaybackCoroutine = StartCoroutine(ContinuousPlaybackLoop());
|
||||||
}
|
}
|
||||||
// If !_runtime_IsStarted, isTriggeringObjectInside is now true,
|
|
||||||
// and CheckForAutoStartIfInside() (called by StartPlayer()) will pick it up.
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
private void OnTriggerExit(Collider other)
|
private void OnTriggerExit(Collider other)
|
||||||
{
|
{
|
||||||
if (!isInitialized || !enabled) return;
|
if (!isInitialized || !enabled) return;
|
||||||
|
|
||||||
int otherLayer = other.gameObject.layer;
|
int otherLayer = other.gameObject.layer;
|
||||||
if ((triggeringLayers.value & (1 << otherLayer)) == 0)
|
if ((triggeringLayers.value & (1 << otherLayer)) == 0) return;
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (other.transform == currentTriggererTransform)
|
if (other.transform == currentTriggererTransform)
|
||||||
{
|
{
|
||||||
Debug.Log($"BarkPlayer ({gameObject.name}): Tracked triggering object '{other.name}' exited.", this);
|
|
||||||
isTriggeringObjectInside = false;
|
isTriggeringObjectInside = false;
|
||||||
currentTriggererTransform = null;
|
currentTriggererTransform = null;
|
||||||
|
|
||||||
|
if (resumeCoroutine != null) StopCoroutine(resumeCoroutine);
|
||||||
|
|
||||||
if (currentPlaybackCoroutine != null)
|
if (currentPlaybackCoroutine != null)
|
||||||
{
|
{
|
||||||
StopCoroutine(currentPlaybackCoroutine);
|
StopCoroutine(currentPlaybackCoroutine);
|
||||||
currentPlaybackCoroutine = null;
|
currentPlaybackCoroutine = null;
|
||||||
Debug.Log($"BarkPlayer ({gameObject.name}): Stopping playback loop due to exit.", this);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -233,7 +258,6 @@ namespace Beyond // Ensure this namespace matches your project
|
|||||||
int barkCount = barkManager.GetBarkCountInEntry(entryIndexToPrepare);
|
int barkCount = barkManager.GetBarkCountInEntry(entryIndexToPrepare);
|
||||||
if (barkCount <= 0)
|
if (barkCount <= 0)
|
||||||
{
|
{
|
||||||
Debug.LogWarning($"BarkPlayer ({gameObject.name}): BarkEntry {entryIndexToPrepare} (from array index {currentEntryArrayIndex}) has no barks. Skipping entry.", this);
|
|
||||||
playbackOrder = new List<int>();
|
playbackOrder = new List<int>();
|
||||||
nextBarkSequenceIndex = 0;
|
nextBarkSequenceIndex = 0;
|
||||||
return false;
|
return false;
|
||||||
@@ -249,9 +273,8 @@ namespace Beyond // Ensure this namespace matches your project
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Apply saved index ONLY if the loaded entry array index matches the current one
|
// If we are resuming mid-sequence (because coroutine was stopped/restarted),
|
||||||
// AND if the shuffle setting at time of save matches current.
|
// we try to respect the saved index, otherwise reset to 0.
|
||||||
// If shuffle setting changed, it's safer to restart the entry.
|
|
||||||
if (currentEntryArrayIndex == m_saveData.savedCurrentEntryArrayIndex && shuffleOrder == m_saveData.wasShuffled)
|
if (currentEntryArrayIndex == m_saveData.savedCurrentEntryArrayIndex && shuffleOrder == m_saveData.wasShuffled)
|
||||||
{
|
{
|
||||||
nextBarkSequenceIndex = Mathf.Clamp(m_saveData.savedNextBarkSequenceIndex, 0, playbackOrder.Count);
|
nextBarkSequenceIndex = Mathf.Clamp(m_saveData.savedNextBarkSequenceIndex, 0, playbackOrder.Count);
|
||||||
@@ -260,36 +283,26 @@ namespace Beyond // Ensure this namespace matches your project
|
|||||||
{
|
{
|
||||||
nextBarkSequenceIndex = 0;
|
nextBarkSequenceIndex = 0;
|
||||||
}
|
}
|
||||||
// Clear the saved next bark index after applying it or deciding not to,
|
|
||||||
// so it's not incorrectly reused if we loop back to this entry without saving/loading.
|
|
||||||
// m_saveData.savedNextBarkSequenceIndex = 0; // Reconsider this - only clear on actual load/new entry start.
|
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
private IEnumerator ContinuousPlaybackLoop()
|
private IEnumerator ContinuousPlaybackLoop()
|
||||||
{
|
{
|
||||||
Debug.Log($"BarkPlayer ({gameObject.name}): Starting playback loop.", this);
|
|
||||||
|
|
||||||
if (barkManagerEntryIndices == null || barkManagerEntryIndices.Length == 0)
|
if (barkManagerEntryIndices == null || barkManagerEntryIndices.Length == 0)
|
||||||
{
|
{
|
||||||
Debug.LogError($"BarkPlayer ({gameObject.name}): Cannot start loop, entry indices array is empty or null.", this);
|
|
||||||
currentPlaybackCoroutine = null;
|
currentPlaybackCoroutine = null;
|
||||||
yield break;
|
yield break;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Outer loop: Continues as long as a valid triggering object is inside AND player is started
|
while (isTriggeringObjectInside && currentTriggererTransform != null && _runtime_IsStarted)
|
||||||
while (isTriggeringObjectInside && currentTriggererTransform != null && _runtime_IsStarted) // Added _runtime_IsStarted check here too
|
|
||||||
{
|
{
|
||||||
|
// Safety check: if dialogue started while we were in a yield, break immediately
|
||||||
|
if (DialogueManager.isConversationActive) break;
|
||||||
|
|
||||||
if (currentEntryArrayIndex >= barkManagerEntryIndices.Length)
|
if (currentEntryArrayIndex >= barkManagerEntryIndices.Length)
|
||||||
{
|
{
|
||||||
currentEntryArrayIndex = 0;
|
currentEntryArrayIndex = 0;
|
||||||
if (barkManagerEntryIndices.Length == 0)
|
|
||||||
{
|
|
||||||
Debug.LogError($"BarkPlayer ({gameObject.name}): Entry indices array became empty during loop?", this);
|
|
||||||
currentPlaybackCoroutine = null; // Ensure it's cleared
|
|
||||||
yield break;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int currentManagerEntryIndex = barkManagerEntryIndices[currentEntryArrayIndex];
|
int currentManagerEntryIndex = barkManagerEntryIndices[currentEntryArrayIndex];
|
||||||
@@ -298,25 +311,30 @@ namespace Beyond // Ensure this namespace matches your project
|
|||||||
if (!canPlayEntry)
|
if (!canPlayEntry)
|
||||||
{
|
{
|
||||||
currentEntryArrayIndex++;
|
currentEntryArrayIndex++;
|
||||||
m_saveData.savedNextBarkSequenceIndex = 0; // Ensure next time this entry is loaded (if looping), it starts fresh
|
m_saveData.savedNextBarkSequenceIndex = 0;
|
||||||
yield return null;
|
yield return null;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
while (nextBarkSequenceIndex < playbackOrder.Count && isTriggeringObjectInside && currentTriggererTransform != null && _runtime_IsStarted)
|
while (nextBarkSequenceIndex < playbackOrder.Count && isTriggeringObjectInside && currentTriggererTransform != null && _runtime_IsStarted)
|
||||||
{
|
{
|
||||||
while (barkManager.IsPlaying && isTriggeringObjectInside && _runtime_IsStarted)
|
// Wait for any other barks (or dialogue) to finish
|
||||||
|
while ((barkManager.IsPlaying || DialogueManager.isConversationActive) && isTriggeringObjectInside && _runtime_IsStarted)
|
||||||
{
|
{
|
||||||
|
// If dialogue becomes active during this wait, the OnDialogueStarted event
|
||||||
|
// will kill this coroutine, so this check is just a backup.
|
||||||
yield return null;
|
yield return null;
|
||||||
}
|
}
|
||||||
if (!isTriggeringObjectInside || currentTriggererTransform == null || !_runtime_IsStarted) break;
|
if (!isTriggeringObjectInside || currentTriggererTransform == null || !_runtime_IsStarted) break;
|
||||||
|
|
||||||
int barkIndexToPlay = playbackOrder[nextBarkSequenceIndex];
|
int barkIndexToPlay = playbackOrder[nextBarkSequenceIndex];
|
||||||
Debug.Log($"BarkPlayer ({gameObject.name}): Playing Bark {nextBarkSequenceIndex + 1}/{playbackOrder.Count} (Actual Index: {barkIndexToPlay}) from Entry {currentManagerEntryIndex}.", this);
|
|
||||||
|
|
||||||
AudioClip playedClip = barkManager.PlayBark(currentManagerEntryIndex, currentTriggererTransform, barkIndexToPlay);
|
AudioClip playedClip = barkManager.PlayBark(currentManagerEntryIndex, currentTriggererTransform, barkIndexToPlay);
|
||||||
nextBarkSequenceIndex++;
|
nextBarkSequenceIndex++;
|
||||||
|
|
||||||
|
// Update Save Data immediately so if we stop mid-sequence we know where we were
|
||||||
|
m_saveData.savedNextBarkSequenceIndex = nextBarkSequenceIndex;
|
||||||
|
|
||||||
float waitTime = delayBetweenBarks;
|
float waitTime = delayBetweenBarks;
|
||||||
if (playedClip != null) { waitTime += Mathf.Max(0f, playedClip.length); }
|
if (playedClip != null) { waitTime += Mathf.Max(0f, playedClip.length); }
|
||||||
|
|
||||||
@@ -325,6 +343,7 @@ namespace Beyond // Ensure this namespace matches your project
|
|||||||
float timer = 0f;
|
float timer = 0f;
|
||||||
while (timer < waitTime && isTriggeringObjectInside && currentTriggererTransform != null && _runtime_IsStarted)
|
while (timer < waitTime && isTriggeringObjectInside && currentTriggererTransform != null && _runtime_IsStarted)
|
||||||
{
|
{
|
||||||
|
if (DialogueManager.isConversationActive) break; // Break timer on dialogue
|
||||||
timer += Time.deltaTime;
|
timer += Time.deltaTime;
|
||||||
yield return null;
|
yield return null;
|
||||||
}
|
}
|
||||||
@@ -334,39 +353,41 @@ namespace Beyond // Ensure this namespace matches your project
|
|||||||
yield return null;
|
yield return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (DialogueManager.isConversationActive) break; // Exit loop if dialogue started
|
||||||
if (!isTriggeringObjectInside || currentTriggererTransform == null || !_runtime_IsStarted) break;
|
if (!isTriggeringObjectInside || currentTriggererTransform == null || !_runtime_IsStarted) break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// If we broke out due to dialogue, exit the outer loop properly
|
||||||
|
if (DialogueManager.isConversationActive) break;
|
||||||
|
|
||||||
if (isTriggeringObjectInside && currentTriggererTransform != null && _runtime_IsStarted)
|
if (isTriggeringObjectInside && currentTriggererTransform != null && _runtime_IsStarted)
|
||||||
{
|
{
|
||||||
Debug.Log($"BarkPlayer ({gameObject.name}): Finished sequence for Entry {currentManagerEntryIndex}.", this);
|
|
||||||
currentEntryArrayIndex++;
|
currentEntryArrayIndex++;
|
||||||
m_saveData.savedNextBarkSequenceIndex = 0; // Reset for next entry
|
m_saveData.savedNextBarkSequenceIndex = 0;
|
||||||
|
// Reset save data sequence index for next entry
|
||||||
|
m_saveData.savedCurrentEntryArrayIndex = currentEntryArrayIndex;
|
||||||
|
|
||||||
if (currentEntryArrayIndex >= barkManagerEntryIndices.Length)
|
if (currentEntryArrayIndex >= barkManagerEntryIndices.Length)
|
||||||
{
|
{
|
||||||
Debug.Log($"BarkPlayer ({gameObject.name}): Finished all entries in the array. Looping back.", this);
|
|
||||||
currentEntryArrayIndex = 0;
|
currentEntryArrayIndex = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (delayBetweenEntries > 0)
|
if (delayBetweenEntries > 0)
|
||||||
{
|
{
|
||||||
Debug.Log($"BarkPlayer ({gameObject.name}): Waiting {delayBetweenEntries}s before next entry.", this);
|
|
||||||
float timer = 0f;
|
float timer = 0f;
|
||||||
while (timer < delayBetweenEntries && isTriggeringObjectInside && currentTriggererTransform != null && _runtime_IsStarted)
|
while (timer < delayBetweenEntries && isTriggeringObjectInside && currentTriggererTransform != null && _runtime_IsStarted)
|
||||||
{
|
{
|
||||||
|
if (DialogueManager.isConversationActive) break;
|
||||||
timer += Time.deltaTime;
|
timer += Time.deltaTime;
|
||||||
yield return null;
|
yield return null;
|
||||||
}
|
}
|
||||||
|
if (DialogueManager.isConversationActive) break;
|
||||||
if (!isTriggeringObjectInside || currentTriggererTransform == null || !_runtime_IsStarted) break;
|
if (!isTriggeringObjectInside || currentTriggererTransform == null || !_runtime_IsStarted) break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Debug.Log($"BarkPlayer ({gameObject.name}): Playback loop finished.", this);
|
if (currentPlaybackCoroutine == this.currentPlaybackCoroutine)
|
||||||
// Only clear if this instance of the coroutine is the one stopping.
|
|
||||||
// If StopPlayer() was called, it would have already nulled currentPlaybackCoroutine.
|
|
||||||
if (currentPlaybackCoroutine == this.currentPlaybackCoroutine) // Check if this is still the active coroutine
|
|
||||||
{
|
{
|
||||||
currentPlaybackCoroutine = null;
|
currentPlaybackCoroutine = null;
|
||||||
}
|
}
|
||||||
@@ -381,23 +402,12 @@ namespace Beyond // Ensure this namespace matches your project
|
|||||||
{
|
{
|
||||||
if (!_runtime_IsStarted)
|
if (!_runtime_IsStarted)
|
||||||
{
|
{
|
||||||
Debug.Log($"BarkPlayer ({gameObject.name}): Player Runtime Explicitly Started.", this);
|
|
||||||
_runtime_IsStarted = true;
|
_runtime_IsStarted = true;
|
||||||
// Clear any previously saved next bark index when explicitly starting,
|
|
||||||
// unless shuffle settings are the same and we are on the same entry.
|
|
||||||
// This is tricky. For now, CheckForAutoStartIfInside will rely on PrepareEntrySequence
|
|
||||||
// to correctly determine if it should resume.
|
|
||||||
// m_saveData.savedNextBarkSequenceIndex = 0; // Maybe too aggressive.
|
|
||||||
|
|
||||||
if (isInitialized)
|
if (isInitialized)
|
||||||
{
|
{
|
||||||
CheckForAutoStartIfInside();
|
CheckForAutoStartIfInside();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
|
||||||
{
|
|
||||||
Debug.Log($"BarkPlayer ({gameObject.name}): Player Runtime was already started.", this);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
[Button]
|
[Button]
|
||||||
@@ -405,53 +415,38 @@ namespace Beyond // Ensure this namespace matches your project
|
|||||||
{
|
{
|
||||||
if (_runtime_IsStarted)
|
if (_runtime_IsStarted)
|
||||||
{
|
{
|
||||||
Debug.Log($"BarkPlayer ({gameObject.name}): Player Runtime Explicitly Stopped.", this);
|
|
||||||
_runtime_IsStarted = false;
|
_runtime_IsStarted = false;
|
||||||
|
if (resumeCoroutine != null) StopCoroutine(resumeCoroutine);
|
||||||
if (currentPlaybackCoroutine != null)
|
if (currentPlaybackCoroutine != null)
|
||||||
{
|
{
|
||||||
StopCoroutine(currentPlaybackCoroutine);
|
StopCoroutine(currentPlaybackCoroutine);
|
||||||
currentPlaybackCoroutine = null;
|
currentPlaybackCoroutine = null;
|
||||||
Debug.Log($"BarkPlayer ({gameObject.name}): Stopping active playback loop due to StopPlayer call.", this);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void CheckForAutoStartIfInside()
|
private void CheckForAutoStartIfInside()
|
||||||
{
|
{
|
||||||
// This is called from Start() and StartPlayer()
|
|
||||||
if (_runtime_IsStarted && isTriggeringObjectInside && currentTriggererTransform != null && currentPlaybackCoroutine == null && isInitialized)
|
if (_runtime_IsStarted && isTriggeringObjectInside && currentTriggererTransform != null && currentPlaybackCoroutine == null && isInitialized)
|
||||||
{
|
{
|
||||||
Debug.Log($"BarkPlayer ({gameObject.name}): Conditions met for auto-start. Object inside, player started, no active coroutine. Starting playback loop.", this);
|
// Double check dialogue isn't running before starting
|
||||||
// Ensure currentEntryArrayIndex is correctly set from save data before starting
|
if (!DialogueManager.isConversationActive)
|
||||||
// (it should already be from Start() or ApplyData(), but good to be sure)
|
{
|
||||||
currentEntryArrayIndex = Mathf.Clamp(m_saveData.savedCurrentEntryArrayIndex, 0, Mathf.Max(0, barkManagerEntryIndices.Length - 1));
|
currentEntryArrayIndex = Mathf.Clamp(m_saveData.savedCurrentEntryArrayIndex, 0, Mathf.Max(0, barkManagerEntryIndices.Length - 1));
|
||||||
// nextBarkSequenceIndex will be determined by PrepareEntrySequence
|
currentPlaybackCoroutine = StartCoroutine(ContinuousPlaybackLoop());
|
||||||
currentPlaybackCoroutine = StartCoroutine(ContinuousPlaybackLoop());
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
#region Save System Integration (Pixel Crushers Saver)
|
#region Save System Integration
|
||||||
|
|
||||||
public override string RecordData()
|
public override string RecordData()
|
||||||
{
|
{
|
||||||
m_saveData.savedIsStarted = this._runtime_IsStarted;
|
m_saveData.savedIsStarted = this._runtime_IsStarted;
|
||||||
m_saveData.savedCurrentEntryArrayIndex = this.currentEntryArrayIndex;
|
m_saveData.savedCurrentEntryArrayIndex = this.currentEntryArrayIndex;
|
||||||
// Only save nextBarkSequenceIndex if a coroutine is running and we are "mid-sequence"
|
m_saveData.savedNextBarkSequenceIndex = this.nextBarkSequenceIndex;
|
||||||
// Otherwise, it should be 0 for the next entry.
|
|
||||||
if (currentPlaybackCoroutine != null && nextBarkSequenceIndex > 0 && nextBarkSequenceIndex < (playbackOrder?.Count ?? 0))
|
|
||||||
{
|
|
||||||
m_saveData.savedNextBarkSequenceIndex = this.nextBarkSequenceIndex;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
// If not actively playing a sequence or at the start/end, save 0.
|
|
||||||
// This means when loading, it will either start the currentEntryArrayIndex from the beginning,
|
|
||||||
// or if currentEntryArrayIndex was incremented after an entry finished, it will start the *new* entry from beginning.
|
|
||||||
m_saveData.savedNextBarkSequenceIndex = 0;
|
|
||||||
}
|
|
||||||
m_saveData.wasShuffled = this.shuffleOrder;
|
m_saveData.wasShuffled = this.shuffleOrder;
|
||||||
|
|
||||||
return SaveSystem.Serialize(m_saveData);
|
return SaveSystem.Serialize(m_saveData);
|
||||||
@@ -462,12 +457,11 @@ namespace Beyond // Ensure this namespace matches your project
|
|||||||
if (string.IsNullOrEmpty(s))
|
if (string.IsNullOrEmpty(s))
|
||||||
{
|
{
|
||||||
_runtime_IsStarted = startAutomaticallyOnLoad;
|
_runtime_IsStarted = startAutomaticallyOnLoad;
|
||||||
m_saveData = new BarkPlayerData(); // Ensure fresh save data container
|
m_saveData = new BarkPlayerData();
|
||||||
m_saveData.savedIsStarted = _runtime_IsStarted; // Sync with runtime
|
m_saveData.savedIsStarted = _runtime_IsStarted;
|
||||||
m_saveData.savedCurrentEntryArrayIndex = 0;
|
m_saveData.savedCurrentEntryArrayIndex = 0;
|
||||||
m_saveData.savedNextBarkSequenceIndex = 0;
|
m_saveData.savedNextBarkSequenceIndex = 0;
|
||||||
m_saveData.wasShuffled = shuffleOrder; // Use current inspector setting
|
m_saveData.wasShuffled = shuffleOrder;
|
||||||
Debug.Log($"BarkPlayer ({gameObject.name}): No save data, using startAutomaticallyOnLoad ({_runtime_IsStarted}).", this);
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -476,22 +470,10 @@ namespace Beyond // Ensure this namespace matches your project
|
|||||||
{
|
{
|
||||||
m_saveData = loadedData;
|
m_saveData = loadedData;
|
||||||
this._runtime_IsStarted = m_saveData.savedIsStarted;
|
this._runtime_IsStarted = m_saveData.savedIsStarted;
|
||||||
// currentEntryArrayIndex and nextBarkSequenceIndex will be used by Start() and PrepareEntrySequence()
|
this.currentEntryArrayIndex = m_saveData.savedCurrentEntryArrayIndex;
|
||||||
Debug.Log($"BarkPlayer ({gameObject.name}): Applied loaded data. Started={_runtime_IsStarted}, EntryIdx={m_saveData.savedCurrentEntryArrayIndex}, BarkIdx={m_saveData.savedNextBarkSequenceIndex}, WasShuffled={m_saveData.wasShuffled}.", this);
|
this.nextBarkSequenceIndex = m_saveData.savedNextBarkSequenceIndex;
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
Debug.LogError($"BarkPlayer ({gameObject.name}): Failed to deserialize save data. Using defaults.", this);
|
|
||||||
_runtime_IsStarted = startAutomaticallyOnLoad;
|
|
||||||
m_saveData = new BarkPlayerData();
|
|
||||||
m_saveData.savedIsStarted = _runtime_IsStarted;
|
|
||||||
m_saveData.savedCurrentEntryArrayIndex = 0;
|
|
||||||
m_saveData.savedNextBarkSequenceIndex = 0;
|
|
||||||
m_saveData.wasShuffled = shuffleOrder;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// After applying data, if loaded state is 'stopped', ensure coroutine is also stopped.
|
|
||||||
// CheckForAutoStartIfInside in Start() will handle restarting if needed.
|
|
||||||
if (!this._runtime_IsStarted && currentPlaybackCoroutine != null)
|
if (!this._runtime_IsStarted && currentPlaybackCoroutine != null)
|
||||||
{
|
{
|
||||||
StopCoroutine(currentPlaybackCoroutine);
|
StopCoroutine(currentPlaybackCoroutine);
|
||||||
|
|||||||
Reference in New Issue
Block a user