Appsflyer done and intersterial ad done

This commit is contained in:
Savya Bikram Shah
2026-06-01 17:58:32 +05:45
parent cb82705189
commit 4976bf14ca
11 changed files with 93 additions and 14 deletions

View File

@@ -48,7 +48,7 @@ namespace Darkmatter.Features.Coloring.UI
_canvasGroup.interactable = true;
_canvasGroup.blocksRaycasts = true;
_activeSequence = Sequence.Create()
_activeSequence = Sequence.Create(useUnscaledTime: true)
.Group(Tween.UIAnchoredPosition(animatedRoot, _shownAnchoredPos, showDuration, Ease.OutBack))
.Group(Tween.Alpha(_canvasGroup, 1f, showDuration, Ease.OutQuad));
return _activeSequence;
@@ -62,7 +62,7 @@ namespace Darkmatter.Features.Coloring.UI
_canvasGroup.blocksRaycasts = false;
var hiddenPos = _shownAnchoredPos + hiddenOffset;
_activeSequence = Sequence.Create()
_activeSequence = Sequence.Create(useUnscaledTime: true)
.Group(Tween.UIAnchoredPosition(animatedRoot, hiddenPos, hideDuration, Ease.InQuad))
.Group(Tween.Alpha(_canvasGroup, 0f, hideDuration, Ease.InQuad))
.ChainCallback(() => gameObject.SetActive(false));

View File

@@ -79,6 +79,13 @@ namespace Darkmatter.Features.GameplayFlow.Systems
_scopeCts = CancellationTokenSource.CreateLinkedTokenSource(cancellation);
var ct = _scopeCts.Token;
// The in-editor AdMob placeholder interstitial pauses via Time.timeScale = 0 and is
// shown fire-and-forget during the Colorbook->Gameplay swap; the Colorbook scene unload
// destroys the placeholder before it can resume, stranding timeScale at 0 (gameplay and
// scaled tweens frozen). Gameplay must never start frozen, so restore it on entry.
// No-op on device, where the real ad clients don't touch timeScale.
Time.timeScale = 1f;
_templateId = _progression.LastOpenedTemplateId;
if (string.IsNullOrEmpty(_templateId))
throw new Exception(

View File

@@ -29,6 +29,7 @@ namespace Darkmatter.Features.ShapeBuilder.Systems
private GameObject _piecePrefab;
private IDisposable _snappedSub;
private IDisposable _unsnappedSub;
private readonly CancellationTokenSource _lifetimeCts = new();
private readonly List<string> _snappedPieceIds = new();
private readonly List<ShapePiece> _pieces = new();
@@ -174,7 +175,32 @@ namespace Darkmatter.Features.ShapeBuilder.Systems
private void CheckIfShapeAssembled()
{
if (_expected > 0 && _snapped == _expected)
_bus.Publish(new ShapeAssembledSignal(_currentTemplateId));
PublishAssembledWhenSettledAsync().Forget();
}
private async UniTaskVoid PublishAssembledWhenSettledAsync()
{
var templateId = _currentTemplateId;
try
{
// Hold the handoff to coloring until the final piece's snap
// animation has finished playing.
await UniTask.WaitWhile(AnyPieceSettling, cancellationToken: _lifetimeCts.Token);
}
catch (OperationCanceledException)
{
return;
}
if (templateId == _currentTemplateId)
_bus.Publish(new ShapeAssembledSignal(templateId));
}
private bool AnyPieceSettling()
{
foreach (var piece in _pieces)
if (piece != null && piece.IsSnapSettling) return true;
return false;
}
private async UniTask TryLoadPiecePrefabAsync(CancellationToken ct)
@@ -241,6 +267,8 @@ namespace Darkmatter.Features.ShapeBuilder.Systems
{
_snappedSub?.Dispose();
_unsnappedSub?.Dispose();
_lifetimeCts.Cancel();
_lifetimeCts.Dispose();
}
}
}

View File

@@ -53,7 +53,7 @@ namespace Darkmatter.Features.ShapeBuilder.UI
_canvasGroup.interactable = true;
_canvasGroup.blocksRaycasts = true;
_activeSequence = Sequence.Create()
_activeSequence = Sequence.Create(useUnscaledTime: true)
.Group(Tween.UIAnchoredPosition(animatedRoot, _shownAnchoredPos, showDuration, Ease.OutBack))
.Group(Tween.Alpha(_canvasGroup, 1f, showDuration, Ease.OutQuad));
return _activeSequence;
@@ -67,7 +67,7 @@ namespace Darkmatter.Features.ShapeBuilder.UI
_canvasGroup.blocksRaycasts = false;
var hiddenPos = _shownAnchoredPos + hiddenOffset;
_activeSequence = Sequence.Create()
_activeSequence = Sequence.Create(useUnscaledTime: true)
.Group(Tween.UIAnchoredPosition(animatedRoot, hiddenPos, hideDuration, Ease.InQuad))
.Group(Tween.Alpha(_canvasGroup, 0f, hideDuration, Ease.InQuad))
.ChainCallback(() => gameObject.SetActive(false));

View File

@@ -1,3 +1,4 @@
using Cysharp.Threading.Tasks;
using Darkmatter.Core.Contracts.Features.History;
using Darkmatter.Core.Contracts.Services.Audio;
using Darkmatter.Core.Data.Signals.Features.ShapeBuilder;
@@ -45,6 +46,7 @@ namespace Darkmatter.Features.ShapeBuilder.UI
private Vector2 _dragSizeDelta;
private Vector3 _dragLocalScale;
private Sequence _previewSeq;
private Sequence _snapSettle;
private bool _locked;
private bool _inPreview;
@@ -57,6 +59,7 @@ namespace Darkmatter.Features.ShapeBuilder.UI
public Vector2 TrayPosition => _trayPos;
public Vector2 TraySize => _traySize;
public SlotMarker ActiveSlot => _activeSlot;
public bool IsSnapSettling => _snapSettle.isAlive;
public void ReassignActiveSlot(SlotMarker slot) => _activeSlot = slot;
@@ -236,12 +239,43 @@ namespace Darkmatter.Features.ShapeBuilder.UI
internal void SnapInternal()
{
_locked = true;
image.raycastTarget = false;
if (_activeSlot != null) _activeSlot.SetOccupied(true);
_sfx.Play(SfxId.ShapeSnap);
// Let the in-flight settle animation play to completion before locking the
// piece into its slot, so the final piece lands smoothly instead of being
// cut short the instant it's dropped.
if (_previewSeq.isAlive)
{
_snapSettle = _previewSeq;
SettleThenFinalizeAsync().Forget();
}
else
{
FinalizeSnapPose();
}
_bus.Publish(new PieceSnappedSignal(_shape.Id));
}
private async UniTaskVoid SettleThenFinalizeAsync()
{
await _snapSettle; // completes when the settle finishes or is stopped
FinalizeSnapPose();
}
private void FinalizeSnapPose()
{
if (this == null || RectTransform == null) return;
_snapSettle = default;
// Bail if the piece was unsnapped (undo) or invalidated while settling.
if (!_locked || _activeSlot == null) return;
StopPreviewTweens();
Lock();
FillSlot();
_sfx.Play(SfxId.ShapeSnap);
_bus.Publish(new PieceSnappedSignal(_shape.Id));
}
private void FillSlot()
@@ -267,6 +301,7 @@ namespace Darkmatter.Features.ShapeBuilder.UI
_activeSlot = null;
Tween.StopAll(onTarget: RectTransform);
_snapSettle = default;
RectTransform.SetParent(parent, worldPositionStays: false);
if (siblingIndex >= 0) RectTransform.SetSiblingIndex(siblingIndex);

View File

@@ -498,6 +498,11 @@ namespace Darkmatter.Services.Ads
{
resolved = true; // stop the watchdog within one poll
unsubscribe(onClosed, onFailed);
// The in-editor placeholder ad pauses via Time.timeScale = 0; if its resume is
// dropped (e.g. the host scene unloads before its close fires) the game stays
// frozen. The ad layer owns that pause, so never leave it stranded. No-op on
// device, where real ad clients don't touch timeScale.
Time.timeScale = 1f;
ScheduleReload(format);
}
}