Files
AppleHillsProduction/Assets/Scripts/DamianExperiments/Picnic/PicnicBehaviour.cs
tschesky 0aa2270e1a Lifecycle System Refactor & Logging Centralization (#56)
## ManagedBehaviour System Refactor

- **Sealed `Awake()`** to prevent override mistakes that break singleton registration
- **Added `OnManagedAwake()`** for early initialization (fires during registration)
- **Renamed lifecycle hook:** `OnManagedAwake()` → `OnManagedStart()` (fires after boot, mirrors Unity's Awake→Start)
- **40 files migrated** to new pattern (2 core, 38 components)
- Eliminated all fragile `private new void Awake()` patterns
- Zero breaking changes - backward compatible

## Centralized Logging System

- **Automatic tagging** via `CallerMemberName` and `CallerFilePath` - logs auto-tagged as `[ClassName][MethodName] message`
- **Unified API:** Single `Logging.Debug/Info/Warning/Error()` replaces custom `LogDebugMessage()` implementations
- **~90 logging call sites** migrated across 10 files
- **10 redundant helper methods** removed
- All logs broadcast via `Logging.OnLogEntryAdded` event for real-time monitoring

## Custom Log Console (Editor Window)

- **Persistent filter popups** for multi-selection (classes, methods, log levels) - windows stay open during selection
- **Search** across class names, methods, and message content
- **Time range filter** with MinMaxSlider
- **Export** filtered logs to timestamped `.txt` files
- **Right-click context menu** for quick filtering and copy actions
- **Visual improvements:** White text, alternating row backgrounds, color-coded log levels
- **Multiple instances** supported for simultaneous system monitoring
- Open via `AppleHills > Custom Log Console`

Co-authored-by: Michal Pikulski <michal@foolhardyhorizons.com>
Co-authored-by: Michal Pikulski <michal.a.pikulski@gmail.com>
Reviewed-on: #56
2025-11-11 08:48:29 +00:00

153 lines
4.1 KiB
C#

using UnityEngine;
using System;
using System.Collections;
using Core;
using Core.Lifecycle;
using Core.SaveLoad;
using UnityEngine.Audio;
public class PicnicBehaviour : ManagedBehaviour
{
[Header("Random Call Settings")]
public float getDistractedMin = 2f;
public float getDistractedMax = 5f;
public float getFlirtyMin = 1f;
public float getFlirtyMax = 3f;
private AppleMachine stateMachine;
private Animator animator;
[Header("The FakeChocolate to destroy!")]
[SerializeField] private GameObject fakeChocolate;
[SerializeField] private GameObject realChocolate;
private AppleAudioSource _audioSource;
public AudioResource distractedAudioClips;
public AudioResource angryAudioClips;
public AudioResource feederClips;
public AudioResource moanerClips;
// Save system configuration
public override bool AutoRegisterForSave => true;
// Runtime state tracking
private bool _fakeChocolateDestroyed;
internal override void OnManagedAwake()
{
stateMachine = GetComponent<AppleMachine>();
animator = GetComponent<Animator>();
_audioSource = GetComponent<AppleAudioSource>();
}
internal override void OnSceneRestoreCompleted()
{
if (_fakeChocolateDestroyed)
{
DestroyChocolateObjects();
}
else
{
StartCoroutine(StateCycleRoutine());
}
}
private IEnumerator StateCycleRoutine()
{
while (true)
{
// Distracted state
float distractedWait = UnityEngine.Random.Range(getDistractedMin, getDistractedMax);
stateMachine.ChangeState("Picnic PPL Distracted");
animator.SetBool("theyDistracted", true);
_audioSource.Stop();
yield return new WaitForSeconds(distractedWait);
// Chilling state
float chillingWait = UnityEngine.Random.Range(getFlirtyMin, getFlirtyMax);
stateMachine.ChangeState("Picnic PPL Chilling");
animator.SetBool("theyDistracted", false);
_audioSource.Stop();
yield return new WaitForSeconds(chillingWait);
}
}
public void triedToStealChocolate()
{
_audioSource.Stop();
animator.SetTrigger("theyAngry");
Logging.Debug("Hey! Don't steal my chocolate!");
_audioSource.audioSource.resource = angryAudioClips;
_audioSource.Play(0);
}
public void destroyFakeChocolate()
{
_fakeChocolateDestroyed = true;
Destroy(fakeChocolate);
Destroy(realChocolate);
}
private void DestroyChocolateObjects()
{
if (fakeChocolate != null)
{
Destroy(fakeChocolate);
fakeChocolate = null;
}
if (realChocolate != null)
{
realChocolate.SetActive(true);
}
}
public void PlayFeederAudio()
{
_audioSource.audioSource.resource = feederClips;
_audioSource.Play(0);
}
public void PlayMoanerAudio()
{
_audioSource.audioSource.resource = moanerClips;
_audioSource.Play(0);
}
public void PlayDistractedAudio()
{
_audioSource.audioSource.resource = distractedAudioClips;
_audioSource.Play(0);
}
internal override string OnSceneSaveRequested()
{
var state = new PicnicBehaviourState { fakeChocolateDestroyed = _fakeChocolateDestroyed };
return JsonUtility.ToJson(state);
}
internal override void OnSceneRestoreRequested(string serializedData)
{
if (string.IsNullOrEmpty(serializedData)) return;
try
{
var state = JsonUtility.FromJson<PicnicBehaviourState>(serializedData);
if (state != null)
{
_fakeChocolateDestroyed = state.fakeChocolateDestroyed;
}
}
catch (Exception ex)
{
Debug.LogWarning($"[PicnicBehaviour] Failed to restore state: {ex.Message}");
}
}
}
[Serializable]
public class PicnicBehaviourState
{
public bool fakeChocolateDestroyed;
}