fixed bug in barks, that was causing UI to disappear to early, fixed issue with bark time calculation, triggers adjustments
This commit is contained in:
@@ -24355,7 +24355,7 @@ MonoBehaviour:
|
||||
type: 4
|
||||
typeString: CustomFieldType_Localization
|
||||
- title: EventGuid
|
||||
value: 0e82506b-79bb-4efc-8472-a3583160edf1
|
||||
value:
|
||||
type: 0
|
||||
typeString:
|
||||
conversationID: 96
|
||||
|
||||
@@ -205,10 +205,11 @@ namespace PixelCrushers.DialogueSystem
|
||||
SetUIElementsActive(true);
|
||||
if (CanTriggerAnimations() && !string.IsNullOrEmpty(animationTransitions.showTrigger))
|
||||
{
|
||||
animator.ResetTrigger(animationTransitions.hideTrigger);
|
||||
animator.SetTrigger(animationTransitions.showTrigger);
|
||||
}
|
||||
CancelInvoke("Hide");
|
||||
var barkDuration = Mathf.Approximately(0, duration) ? DialogueManager.GetBarkDuration(subtitleText) : duration;
|
||||
var barkDuration = Math.Max(DialogueManager.GetBarkDuration(subtitleText) ,duration);
|
||||
if (!(waitUntilSequenceEnds || waitForContinueButton)) Invoke("Hide", barkDuration);
|
||||
if (waitUntilSequenceEnds) numSequencesActive++;
|
||||
doneTime = waitForContinueButton ? Mathf.Infinity : (DialogueTime.time + barkDuration);
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -81,13 +81,9 @@ namespace Beyond // Ensure this namespace matches your project
|
||||
|
||||
public override void Awake()
|
||||
{
|
||||
// Set initial state based on Inspector setting *before* base.Awake potentially calls ApplyData
|
||||
// If save data exists, ApplyData will overwrite this.
|
||||
_runtime_IsStarted = startAutomaticallyOnLoad;
|
||||
base.Awake();
|
||||
|
||||
base.Awake(); // This might call ApplyData via Save System
|
||||
|
||||
// --- Component & Initial Setup ---
|
||||
triggerCollider = GetComponent<Collider>();
|
||||
if (!triggerCollider.isTrigger)
|
||||
{
|
||||
@@ -95,13 +91,12 @@ namespace Beyond // Ensure this namespace matches your project
|
||||
triggerCollider.isTrigger = true;
|
||||
}
|
||||
|
||||
// --- Default LayerMask ---
|
||||
if (triggeringLayers.value == 0) // LayerMask is empty/unassigned
|
||||
if (triggeringLayers.value == 0)
|
||||
{
|
||||
int playerLayer = LayerMask.NameToLayer("Player");
|
||||
if (playerLayer != -1)
|
||||
{
|
||||
triggeringLayers = LayerMask.GetMask("Player"); // Default to Player layer
|
||||
triggeringLayers = LayerMask.GetMask("Player");
|
||||
Debug.LogWarning($"BarkPlayer on {gameObject.name}: Triggering Layers not set in inspector, defaulting to 'Player' layer.", this);
|
||||
}
|
||||
else
|
||||
@@ -109,13 +104,10 @@ namespace Beyond // Ensure this namespace matches your project
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
// Final state of _runtime_IsStarted reflects Inspector default OR loaded save data.
|
||||
}
|
||||
|
||||
private void Start()
|
||||
{
|
||||
// --- Get BarkManager Instance ---
|
||||
barkManager = BarkManager.Instance;
|
||||
if (barkManager == null)
|
||||
{
|
||||
@@ -124,12 +116,8 @@ namespace Beyond // Ensure this namespace matches your project
|
||||
return;
|
||||
}
|
||||
|
||||
// --- Apply Loaded Indices ---
|
||||
// Ensure array index is valid even if array size changed since saving
|
||||
currentEntryArrayIndex = Mathf.Clamp(m_saveData.savedCurrentEntryArrayIndex, 0, Mathf.Max(0, barkManagerEntryIndices.Length - 1));
|
||||
// nextBarkSequenceIndex will be applied when PrepareEntrySequence is called
|
||||
|
||||
// --- Validate Entry Indices ---
|
||||
if (barkManagerEntryIndices == null || barkManagerEntryIndices.Length == 0)
|
||||
{
|
||||
Debug.LogWarning($"BarkPlayer ({gameObject.name}): No Bark Manager Entry Indices provided. Disabling.", this);
|
||||
@@ -147,10 +135,7 @@ namespace Beyond // Ensure this namespace matches your project
|
||||
}
|
||||
|
||||
isInitialized = true;
|
||||
|
||||
// Check if we should start playing immediately after initialization
|
||||
// (e.g., if loaded state is 'started' and player is already inside trigger)
|
||||
CheckForAutoStartIfInside();
|
||||
CheckForAutoStartIfInside(); // Check immediately if conditions are met
|
||||
}
|
||||
|
||||
private void OnDrawGizmos()
|
||||
@@ -158,10 +143,9 @@ namespace Beyond // Ensure this namespace matches your project
|
||||
Collider col = GetComponent<Collider>();
|
||||
if (col != null)
|
||||
{
|
||||
Gizmos.color = isTriggeringObjectInside ? new Color(1f, 0.5f, 0.5f, 0.4f) : new Color(0.5f, 1f, 0.5f, 0.3f); // Red when active
|
||||
Gizmos.color = isTriggeringObjectInside ? new Color(1f, 0.5f, 0.5f, 0.4f) : new Color(0.5f, 1f, 0.5f, 0.3f);
|
||||
if (col is BoxCollider box) Gizmos.DrawCube(transform.TransformPoint(box.center), Vector3.Scale(box.size, transform.lossyScale));
|
||||
else if (col is SphereCollider sphere) Gizmos.DrawSphere(transform.TransformPoint(sphere.center), sphere.radius * MaxComponent(transform.lossyScale));
|
||||
// Add other collider types if needed
|
||||
}
|
||||
}
|
||||
|
||||
@@ -171,8 +155,8 @@ namespace Beyond // Ensure this namespace matches your project
|
||||
|
||||
private void OnTriggerEnter(Collider other)
|
||||
{
|
||||
// Ignore if not initialized, not enabled, or runtime state is not 'Started'
|
||||
if (!isInitialized || !enabled || !_runtime_IsStarted) return;
|
||||
// Only ignore if not initialized or component is disabled
|
||||
if (!isInitialized || !enabled) return;
|
||||
|
||||
// --- Layer Check ---
|
||||
int otherLayer = other.gameObject.layer;
|
||||
@@ -183,64 +167,65 @@ namespace Beyond // Ensure this namespace matches your project
|
||||
|
||||
// --- Check if already processing an object ---
|
||||
// This prevents multiple triggering objects from interfering. Only the first one in matters.
|
||||
if (isTriggeringObjectInside) return;
|
||||
if (isTriggeringObjectInside && other.transform != currentTriggererTransform)
|
||||
{
|
||||
// If another object enters while one is already tracked, ignore the new one.
|
||||
// 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;
|
||||
}
|
||||
if (isTriggeringObjectInside) return; // Simplified: if already tracking one, ignore others.
|
||||
|
||||
// --- Valid Trigger ---
|
||||
Debug.Log($"BarkPlayer ({gameObject.name}): Triggering object '{other.name}' entered.", this);
|
||||
// --- 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 not already running ---
|
||||
if (currentPlaybackCoroutine == null)
|
||||
// --- 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)
|
||||
{
|
||||
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));
|
||||
// nextBarkSequenceIndex will be set by PrepareEntrySequence inside the coroutine
|
||||
currentPlaybackCoroutine = StartCoroutine(ContinuousPlaybackLoop());
|
||||
}
|
||||
// If !_runtime_IsStarted, isTriggeringObjectInside is now true,
|
||||
// and CheckForAutoStartIfInside() (called by StartPlayer()) will pick it up.
|
||||
}
|
||||
|
||||
|
||||
private void OnTriggerExit(Collider other)
|
||||
{
|
||||
if (!isInitialized || !enabled) return;
|
||||
|
||||
// --- Layer Check ---
|
||||
int otherLayer = other.gameObject.layer;
|
||||
if ((triggeringLayers.value & (1 << otherLayer)) == 0)
|
||||
{
|
||||
return; // Ignore exit events from non-triggering layers
|
||||
return;
|
||||
}
|
||||
|
||||
// --- Check if the *tracked* object is the one exiting ---
|
||||
if (other.transform == currentTriggererTransform)
|
||||
{
|
||||
Debug.Log($"BarkPlayer ({gameObject.name}): Triggering object '{other.name}' exited.", this);
|
||||
Debug.Log($"BarkPlayer ({gameObject.name}): Tracked triggering object '{other.name}' exited.", this);
|
||||
isTriggeringObjectInside = false;
|
||||
currentTriggererTransform = null; // Clear the stored transform
|
||||
currentTriggererTransform = null;
|
||||
|
||||
// --- Stop the Playback Coroutine ---
|
||||
if (currentPlaybackCoroutine != null)
|
||||
{
|
||||
StopCoroutine(currentPlaybackCoroutine);
|
||||
currentPlaybackCoroutine = null;
|
||||
Debug.Log($"BarkPlayer ({gameObject.name}): Stopping playback loop due to exit.", this);
|
||||
// Optional: Immediately stop BarkManager audio?
|
||||
// if (barkManager != null && barkManager.IsPlaying) barkManager.m_audioSource.Stop();
|
||||
}
|
||||
}
|
||||
// Else: Some other object on a triggering layer exited, but the primary one is still inside. Do nothing.
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Playback Logic
|
||||
|
||||
/// <summary>
|
||||
/// Sets up the playbackOrder list for a specific BarkManager entry index.
|
||||
/// Resets or applies saved nextBarkSequenceIndex.
|
||||
/// </summary>
|
||||
/// <param name="entryIndexToPrepare">The index within BarkManager's m_barks array.</param>
|
||||
/// <returns>True if preparation was successful (entry has barks), false otherwise.</returns>
|
||||
private bool PrepareEntrySequence(int entryIndexToPrepare)
|
||||
{
|
||||
if (barkManager == null) return false;
|
||||
@@ -249,169 +234,141 @@ namespace Beyond // Ensure this namespace matches your project
|
||||
if (barkCount <= 0)
|
||||
{
|
||||
Debug.LogWarning($"BarkPlayer ({gameObject.name}): BarkEntry {entryIndexToPrepare} (from array index {currentEntryArrayIndex}) has no barks. Skipping entry.", this);
|
||||
playbackOrder = new List<int>(); // Ensure list is empty
|
||||
playbackOrder = new List<int>();
|
||||
nextBarkSequenceIndex = 0;
|
||||
return false; // Indicate nothing to play for this entry
|
||||
return false;
|
||||
}
|
||||
|
||||
// Generate sequence order (sequential or shuffled)
|
||||
playbackOrder = Enumerable.Range(0, barkCount).ToList();
|
||||
if (shuffleOrder)
|
||||
{
|
||||
// Simple Fisher-Yates shuffle
|
||||
for (int i = playbackOrder.Count - 1; i > 0; i--)
|
||||
{
|
||||
int j = Random.Range(0, i + 1);
|
||||
// Tuple swap is concise
|
||||
(playbackOrder[i], playbackOrder[j]) = (playbackOrder[j], playbackOrder[i]);
|
||||
}
|
||||
// Debug.Log($"BarkPlayer ({gameObject.name}): Shuffled order for entry {entryIndexToPrepare}.", this);
|
||||
}
|
||||
|
||||
// Reset sequence progress. Apply saved index ONLY if the loaded array index matches the current one.
|
||||
if (currentEntryArrayIndex == m_saveData.savedCurrentEntryArrayIndex)
|
||||
// Apply saved index ONLY if the loaded entry array index matches the current one
|
||||
// AND if the shuffle setting at time of save matches current.
|
||||
// If shuffle setting changed, it's safer to restart the entry.
|
||||
if (currentEntryArrayIndex == m_saveData.savedCurrentEntryArrayIndex && shuffleOrder == m_saveData.wasShuffled)
|
||||
{
|
||||
nextBarkSequenceIndex = Mathf.Clamp(m_saveData.savedNextBarkSequenceIndex, 0, playbackOrder.Count);
|
||||
// Debug.Log($"BarkPlayer ({gameObject.name}): Resuming entry {entryIndexToPrepare} at bark index {nextBarkSequenceIndex}.", this);
|
||||
}
|
||||
else
|
||||
{
|
||||
nextBarkSequenceIndex = 0; // Start new entry from beginning if array index differs from saved
|
||||
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; // Preparation successful
|
||||
return true;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Main coroutine managing the playback loop through entries and barks.
|
||||
/// </summary>
|
||||
private IEnumerator ContinuousPlaybackLoop()
|
||||
{
|
||||
Debug.Log($"BarkPlayer ({gameObject.name}): Starting playback loop.", this);
|
||||
|
||||
// Initial check for valid configuration
|
||||
if (barkManagerEntryIndices == null || barkManagerEntryIndices.Length == 0)
|
||||
{
|
||||
Debug.LogError($"BarkPlayer ({gameObject.name}): Cannot start loop, entry indices array is empty or null.", this);
|
||||
currentPlaybackCoroutine = null; // Ensure coroutine reference is cleared
|
||||
currentPlaybackCoroutine = null;
|
||||
yield break;
|
||||
}
|
||||
|
||||
// Outer loop: Continues as long as a valid triggering object is inside
|
||||
while (isTriggeringObjectInside && currentTriggererTransform != null)
|
||||
// Outer loop: Continues as long as a valid triggering object is inside AND player is started
|
||||
while (isTriggeringObjectInside && currentTriggererTransform != null && _runtime_IsStarted) // Added _runtime_IsStarted check here too
|
||||
{
|
||||
// --- Step 1: Prepare for Current Entry ---
|
||||
// Safety check/loop wrap for the array index
|
||||
if (currentEntryArrayIndex >= barkManagerEntryIndices.Length)
|
||||
{
|
||||
currentEntryArrayIndex = 0;
|
||||
if (barkManagerEntryIndices.Length == 0)
|
||||
{ // Should be caught earlier, but double-check
|
||||
{
|
||||
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];
|
||||
// Debug.Log($"BarkPlayer ({gameObject.name}): Preparing Entry Index: {currentManagerEntryIndex} (Array Pos: {currentEntryArrayIndex}).", this);
|
||||
|
||||
// Prepare the sequence (generate playbackOrder, set nextBarkSequenceIndex)
|
||||
bool canPlayEntry = PrepareEntrySequence(currentManagerEntryIndex);
|
||||
|
||||
if (!canPlayEntry) // Skip this entry if it has no barks
|
||||
if (!canPlayEntry)
|
||||
{
|
||||
// Debug.Log($"BarkPlayer ({gameObject.name}): Skipping empty BarkEntry {currentManagerEntryIndex}.", this);
|
||||
currentEntryArrayIndex++; // Move immediately to the next entry index
|
||||
yield return null; // Wait a frame before checking the next entry in the outer loop
|
||||
continue; // Go to next iteration of the outer while loop (skips delays below)
|
||||
currentEntryArrayIndex++;
|
||||
m_saveData.savedNextBarkSequenceIndex = 0; // Ensure next time this entry is loaded (if looping), it starts fresh
|
||||
yield return null;
|
||||
continue;
|
||||
}
|
||||
|
||||
|
||||
// --- Step 2: Inner Loop - Play Barks within the Current Entry ---
|
||||
while (nextBarkSequenceIndex < playbackOrder.Count && isTriggeringObjectInside && currentTriggererTransform != null)
|
||||
while (nextBarkSequenceIndex < playbackOrder.Count && isTriggeringObjectInside && currentTriggererTransform != null && _runtime_IsStarted)
|
||||
{
|
||||
// Wait for BarkManager's AudioSource if it's busy
|
||||
while (barkManager.IsPlaying && isTriggeringObjectInside)
|
||||
while (barkManager.IsPlaying && isTriggeringObjectInside && _runtime_IsStarted)
|
||||
{
|
||||
yield return null; // Wait a frame
|
||||
yield return null;
|
||||
}
|
||||
// Re-check condition after waiting, player might have left
|
||||
if (!isTriggeringObjectInside || currentTriggererTransform == null) break;
|
||||
if (!isTriggeringObjectInside || currentTriggererTransform == null || !_runtime_IsStarted) break;
|
||||
|
||||
|
||||
// Play the specific bark for this step in the sequence
|
||||
int barkIndexToPlay = playbackOrder[nextBarkSequenceIndex];
|
||||
Debug.Log($"BarkPlayer ({gameObject.name}): Playing Bark {nextBarkSequenceIndex + 1}/{playbackOrder.Count} (Actual Index: {barkIndexToPlay}) from Entry {currentManagerEntryIndex}.", this);
|
||||
|
||||
// Play using the specific index, passing the triggerer's transform
|
||||
AudioClip playedClip = barkManager.PlayBark(currentManagerEntryIndex, currentTriggererTransform, barkIndexToPlay);
|
||||
nextBarkSequenceIndex++;
|
||||
|
||||
nextBarkSequenceIndex++; // Increment progress within this entry's sequence
|
||||
|
||||
// Wait for the bark's duration plus the inter-bark delay
|
||||
float waitTime = delayBetweenBarks;
|
||||
if (playedClip != null) { waitTime += Mathf.Max(0f, playedClip.length); } // Ensure non-negative length
|
||||
if (playedClip != null) { waitTime += Mathf.Max(0f, playedClip.length); }
|
||||
|
||||
// Perform the wait, checking continuously if the player leaves
|
||||
if (waitTime > 0)
|
||||
{
|
||||
float timer = 0f;
|
||||
while (timer < waitTime && isTriggeringObjectInside && currentTriggererTransform != null)
|
||||
while (timer < waitTime && isTriggeringObjectInside && currentTriggererTransform != null && _runtime_IsStarted)
|
||||
{
|
||||
timer += Time.deltaTime;
|
||||
yield return null; // Wait one frame
|
||||
yield return null;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// Minimum one frame wait even if no delay/clip length
|
||||
yield return null;
|
||||
}
|
||||
|
||||
// If player left during wait, break inner loop
|
||||
if (!isTriggeringObjectInside || currentTriggererTransform == null) break;
|
||||
if (!isTriggeringObjectInside || currentTriggererTransform == null || !_runtime_IsStarted) break;
|
||||
}
|
||||
|
||||
} // --- End of Inner Loop (Barks within Entry) ---
|
||||
|
||||
|
||||
// --- Step 3: Transition to Next Entry (if player didn't exit) ---
|
||||
if (isTriggeringObjectInside && currentTriggererTransform != null)
|
||||
if (isTriggeringObjectInside && currentTriggererTransform != null && _runtime_IsStarted)
|
||||
{
|
||||
// Current entry sequence finished normally
|
||||
Debug.Log($"BarkPlayer ({gameObject.name}): Finished sequence for Entry {currentManagerEntryIndex}.", this);
|
||||
currentEntryArrayIndex++;
|
||||
m_saveData.savedNextBarkSequenceIndex = 0; // Reset for next entry
|
||||
|
||||
currentEntryArrayIndex++; // Move to the next entry index in the array
|
||||
|
||||
// Check for wrapping / end of all entries in the array
|
||||
if (currentEntryArrayIndex >= barkManagerEntryIndices.Length)
|
||||
{
|
||||
Debug.Log($"BarkPlayer ({gameObject.name}): Finished all entries in the array. Looping back.", this);
|
||||
currentEntryArrayIndex = 0; // Loop back to the start of the array
|
||||
currentEntryArrayIndex = 0;
|
||||
}
|
||||
|
||||
// Wait for the specified delay BETWEEN entries
|
||||
if (delayBetweenEntries > 0)
|
||||
{
|
||||
Debug.Log($"BarkPlayer ({gameObject.name}): Waiting {delayBetweenEntries}s before next entry.", this);
|
||||
float timer = 0f;
|
||||
while (timer < delayBetweenEntries && isTriggeringObjectInside && currentTriggererTransform != null)
|
||||
while (timer < delayBetweenEntries && isTriggeringObjectInside && currentTriggererTransform != null && _runtime_IsStarted)
|
||||
{
|
||||
timer += Time.deltaTime;
|
||||
yield return null; // Wait one frame
|
||||
yield return null;
|
||||
}
|
||||
// If player left during delay, break outer loop
|
||||
if (!isTriggeringObjectInside || currentTriggererTransform == null) break;
|
||||
if (!isTriggeringObjectInside || currentTriggererTransform == null || !_runtime_IsStarted) break;
|
||||
}
|
||||
// The outer loop will then continue, preparing the next entry
|
||||
}
|
||||
}
|
||||
|
||||
} // --- End of Outer Loop (isTriggeringObjectInside) ---
|
||||
|
||||
Debug.Log($"BarkPlayer ({gameObject.name}): Playback loop finished (Triggering object left or component stopped).", this);
|
||||
// Clear coroutine reference *if* this coroutine instance is the one finishing
|
||||
if (currentPlaybackCoroutine != null && (!isTriggeringObjectInside || currentTriggererTransform == null))
|
||||
Debug.Log($"BarkPlayer ({gameObject.name}): Playback loop finished.", this);
|
||||
// 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;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -419,60 +376,57 @@ namespace Beyond // Ensure this namespace matches your project
|
||||
|
||||
#region Public Control Methods
|
||||
|
||||
/// <summary>
|
||||
/// Enables the BarkPlayer's runtime operation. It will start playing sequences when triggered.
|
||||
/// If a triggering object is already inside, playback may start immediately.
|
||||
/// </summary>
|
||||
[Button] // Example for Odin Inspector button
|
||||
[Button]
|
||||
public void StartPlayer()
|
||||
{
|
||||
if (!_runtime_IsStarted)
|
||||
{
|
||||
Debug.Log($"BarkPlayer ({gameObject.name}): Player Runtime Started.", this);
|
||||
Debug.Log($"BarkPlayer ({gameObject.name}): Player Runtime Explicitly Started.", this);
|
||||
_runtime_IsStarted = true;
|
||||
// If already initialized, check if we need to immediately start playback
|
||||
// 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)
|
||||
{
|
||||
CheckForAutoStartIfInside();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
Debug.Log($"BarkPlayer ({gameObject.name}): Player Runtime was already started.", this);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Disables the BarkPlayer's runtime operation. Stops any current playback and ignores future triggers.
|
||||
/// </summary>
|
||||
[Button] // Example for Odin Inspector button
|
||||
[Button]
|
||||
public void StopPlayer()
|
||||
{
|
||||
if (_runtime_IsStarted)
|
||||
{
|
||||
Debug.Log($"BarkPlayer ({gameObject.name}): Player Runtime Stopped.", this);
|
||||
Debug.Log($"BarkPlayer ({gameObject.name}): Player Runtime Explicitly Stopped.", this);
|
||||
_runtime_IsStarted = false;
|
||||
|
||||
// Stop any currently running playback coroutine
|
||||
if (currentPlaybackCoroutine != null)
|
||||
{
|
||||
StopCoroutine(currentPlaybackCoroutine);
|
||||
currentPlaybackCoroutine = null; // Clear the reference
|
||||
Debug.Log($"BarkPlayer ({gameObject.name}): Stopping active playback loop.", this);
|
||||
// Optional: Immediately stop BarkManager audio?
|
||||
// if (barkManager != null && barkManager.IsPlaying) barkManager.m_audioSource.Stop();
|
||||
currentPlaybackCoroutine = null;
|
||||
Debug.Log($"BarkPlayer ({gameObject.name}): Stopping active playback loop due to StopPlayer call.", this);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Checks if the player is currently inside the trigger and starts the playback loop
|
||||
/// if the BarkPlayer is started (_runtime_IsStarted=true) but the loop isn't currently running.
|
||||
/// Useful after initialization (in Start) or after calling StartPlayer manually.
|
||||
/// </summary>
|
||||
private void CheckForAutoStartIfInside()
|
||||
{
|
||||
// This is called from Start() and StartPlayer()
|
||||
if (_runtime_IsStarted && isTriggeringObjectInside && currentTriggererTransform != null && currentPlaybackCoroutine == null && isInitialized)
|
||||
{
|
||||
Debug.Log($"BarkPlayer ({gameObject.name}): Triggering object already inside and player is started. Starting playback loop.", this);
|
||||
// Ensure indices are correctly set from save data before starting
|
||||
Debug.Log($"BarkPlayer ({gameObject.name}): Conditions met for auto-start. Object inside, player started, no active coroutine. Starting playback loop.", this);
|
||||
// Ensure currentEntryArrayIndex is correctly set from save data before starting
|
||||
// (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));
|
||||
// nextBarkSequenceIndex will be determined by PrepareEntrySequence
|
||||
currentPlaybackCoroutine = StartCoroutine(ContinuousPlaybackLoop());
|
||||
}
|
||||
}
|
||||
@@ -483,66 +437,72 @@ namespace Beyond // Ensure this namespace matches your project
|
||||
|
||||
public override string RecordData()
|
||||
{
|
||||
// Update save data container with current runtime state
|
||||
m_saveData.savedIsStarted = this._runtime_IsStarted;
|
||||
m_saveData.savedCurrentEntryArrayIndex = this.currentEntryArrayIndex;
|
||||
m_saveData.savedNextBarkSequenceIndex = this.nextBarkSequenceIndex;
|
||||
m_saveData.wasShuffled = this.shuffleOrder; // Record shuffle setting at time of save
|
||||
// Only save nextBarkSequenceIndex if a coroutine is running and we are "mid-sequence"
|
||||
// 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;
|
||||
|
||||
// Serialize the save data container
|
||||
return SaveSystem.Serialize(m_saveData);
|
||||
}
|
||||
|
||||
public override void ApplyData(string s)
|
||||
{
|
||||
// Handle case where there is no save data for this component
|
||||
if (string.IsNullOrEmpty(s))
|
||||
{
|
||||
// No save data - runtime state keeps the value set by startAutomaticallyOnLoad in Awake
|
||||
_runtime_IsStarted = startAutomaticallyOnLoad;
|
||||
// Reset progress indices if no save data
|
||||
m_saveData = new BarkPlayerData(); // Ensure fresh save data container
|
||||
m_saveData.savedIsStarted = _runtime_IsStarted; // Sync with runtime
|
||||
m_saveData.savedCurrentEntryArrayIndex = 0;
|
||||
m_saveData.savedNextBarkSequenceIndex = 0;
|
||||
Debug.Log($"BarkPlayer ({gameObject.name}): No save data found, using startAutomaticallyOnLoad ({startAutomaticallyOnLoad}).", this);
|
||||
m_saveData.wasShuffled = shuffleOrder; // Use current inspector setting
|
||||
Debug.Log($"BarkPlayer ({gameObject.name}): No save data, using startAutomaticallyOnLoad ({_runtime_IsStarted}).", this);
|
||||
return;
|
||||
}
|
||||
|
||||
// Deserialize the saved data string
|
||||
var loadedData = SaveSystem.Deserialize<BarkPlayerData>(s);
|
||||
if (loadedData != null)
|
||||
{
|
||||
m_saveData = loadedData; // Store the loaded data
|
||||
// Apply the loaded runtime state
|
||||
m_saveData = loadedData;
|
||||
this._runtime_IsStarted = m_saveData.savedIsStarted;
|
||||
// Indices will be applied in Start() / PrepareEntrySequence() using m_saveData
|
||||
Debug.Log($"BarkPlayer ({gameObject.name}): Applied loaded data. Started={_runtime_IsStarted}, EntryIdx={m_saveData.savedCurrentEntryArrayIndex}, BarkIdx={m_saveData.savedNextBarkSequenceIndex}.", this);
|
||||
// currentEntryArrayIndex and nextBarkSequenceIndex will be used by Start() and PrepareEntrySequence()
|
||||
Debug.Log($"BarkPlayer ({gameObject.name}): Applied loaded data. Started={_runtime_IsStarted}, EntryIdx={m_saveData.savedCurrentEntryArrayIndex}, BarkIdx={m_saveData.savedNextBarkSequenceIndex}, WasShuffled={m_saveData.wasShuffled}.", this);
|
||||
}
|
||||
else
|
||||
{
|
||||
Debug.LogError($"BarkPlayer ({gameObject.name}): Failed to deserialize save data. Using defaults.", this);
|
||||
// Fallback: use inspector setting if deserialize failed
|
||||
this._runtime_IsStarted = startAutomaticallyOnLoad;
|
||||
_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, ensure consistency: if loaded state is 'stopped', stop coroutine
|
||||
// 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)
|
||||
{
|
||||
StopCoroutine(currentPlaybackCoroutine);
|
||||
currentPlaybackCoroutine = null;
|
||||
}
|
||||
// The CheckForAutoStartIfInside() call in Start() will handle restarting the
|
||||
// coroutine if the loaded state is 'started' and the player is inside the trigger.
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Helper Methods
|
||||
|
||||
/// <summary> Helper to find the largest component of a Vector3 (for Gizmos). </summary>
|
||||
private float MaxComponent(Vector3 v) => Mathf.Max(Mathf.Max(v.x, v.y), v.z);
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user