analyitcs
This commit is contained in:
@@ -0,0 +1,8 @@
|
|||||||
|
fileFormatVersion: 2
|
||||||
|
guid: 89ff3ec1d970c4031b6e9f765b93c4e7
|
||||||
|
folderAsset: yes
|
||||||
|
DefaultImporter:
|
||||||
|
externalObjects: {}
|
||||||
|
userData:
|
||||||
|
assetBundleName:
|
||||||
|
assetBundleVariant:
|
||||||
@@ -0,0 +1,12 @@
|
|||||||
|
using System.Collections.Generic;
|
||||||
|
|
||||||
|
namespace Darkmatter.Core.Contracts.Services.Analytics
|
||||||
|
{
|
||||||
|
public interface IAnalyticsService
|
||||||
|
{
|
||||||
|
void LogEvent(string name);
|
||||||
|
void LogEvent(string name, string paramName, string paramValue);
|
||||||
|
void LogEvent(string name, IReadOnlyDictionary<string, object> parameters);
|
||||||
|
void SetUserProperty(string name, string value);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,2 @@
|
|||||||
|
fileFormatVersion: 2
|
||||||
|
guid: a36684ef8a2124c469c6ac2c8c4fef2e
|
||||||
@@ -0,0 +1,8 @@
|
|||||||
|
fileFormatVersion: 2
|
||||||
|
guid: a60852842d4a74363904d1aa6e2c8fb5
|
||||||
|
folderAsset: yes
|
||||||
|
DefaultImporter:
|
||||||
|
externalObjects: {}
|
||||||
|
userData:
|
||||||
|
assetBundleName:
|
||||||
|
assetBundleVariant:
|
||||||
@@ -0,0 +1,4 @@
|
|||||||
|
namespace Darkmatter.Core.Data.Signals.Features.GameplayFlow
|
||||||
|
{
|
||||||
|
public record struct DrawingCompletedSignal(string TemplateId, int CompletionCount);
|
||||||
|
}
|
||||||
@@ -0,0 +1,2 @@
|
|||||||
|
fileFormatVersion: 2
|
||||||
|
guid: 4e2a47489fe7c4886993338327772aac
|
||||||
@@ -14,6 +14,7 @@ using Darkmatter.Core.Contracts.Services.Scenes;
|
|||||||
using Darkmatter.Core.Data.Dynamic.Features.Progression;
|
using Darkmatter.Core.Data.Dynamic.Features.Progression;
|
||||||
using Darkmatter.Core.Data.Signals.Features.Coloring;
|
using Darkmatter.Core.Data.Signals.Features.Coloring;
|
||||||
using Darkmatter.Core.Data.Signals.Features.Drawing;
|
using Darkmatter.Core.Data.Signals.Features.Drawing;
|
||||||
|
using Darkmatter.Core.Data.Signals.Features.GameplayFlow;
|
||||||
using Darkmatter.Core.Data.Signals.Features.ShapeBuilder;
|
using Darkmatter.Core.Data.Signals.Features.ShapeBuilder;
|
||||||
using Darkmatter.Core.Enums.Features.Progression;
|
using Darkmatter.Core.Enums.Features.Progression;
|
||||||
using Darkmatter.Core.Enums.Services.Audio;
|
using Darkmatter.Core.Enums.Services.Audio;
|
||||||
@@ -133,6 +134,8 @@ namespace Darkmatter.Features.GameplayFlow.Systems
|
|||||||
_sfx.Play(SfxId.LevelComplete);
|
_sfx.Play(SfxId.LevelComplete);
|
||||||
await _coloring.PlayCompletionAnimationAsync(ct);
|
await _coloring.PlayCompletionAnimationAsync(ct);
|
||||||
_progression.MarkCompleted(_templateId);
|
_progression.MarkCompleted(_templateId);
|
||||||
|
var progressAfter = _progression.GetProgress(_templateId);
|
||||||
|
_bus.Publish(new DrawingCompletedSignal(_templateId, progressAfter?.completionCount ?? 1));
|
||||||
|
|
||||||
var nextId = _catalog.GetNextTemplate(_templateId);
|
var nextId = _catalog.GetNextTemplate(_templateId);
|
||||||
if (string.IsNullOrEmpty(nextId))
|
if (string.IsNullOrEmpty(nextId))
|
||||||
|
|||||||
@@ -1,3 +1,4 @@
|
|||||||
|
using Darkmatter.Core.Contracts.Services.Analytics;
|
||||||
using Darkmatter.Libs.Installers;
|
using Darkmatter.Libs.Installers;
|
||||||
using UnityEngine;
|
using UnityEngine;
|
||||||
using VContainer;
|
using VContainer;
|
||||||
@@ -9,7 +10,8 @@ namespace Darkmatter.Services.Analytics
|
|||||||
{
|
{
|
||||||
public void Register(IContainerBuilder builder)
|
public void Register(IContainerBuilder builder)
|
||||||
{
|
{
|
||||||
builder.RegisterEntryPoint<FirebaseAnalyticsSystem>();
|
builder.RegisterEntryPoint<FirebaseAnalyticsSystem>().As<IAnalyticsService>();
|
||||||
|
builder.RegisterEntryPoint<AnalyticsTracker>();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -7,7 +7,9 @@
|
|||||||
"GUID:f51ebe6a0ceec4240a699833d6309b23",
|
"GUID:f51ebe6a0ceec4240a699833d6309b23",
|
||||||
"GUID:b0214a6008ed146ff8f122a6a9c2f6cc",
|
"GUID:b0214a6008ed146ff8f122a6a9c2f6cc",
|
||||||
"GUID:f8c64bb88d959406689053ae3f31183d",
|
"GUID:f8c64bb88d959406689053ae3f31183d",
|
||||||
"GUID:a0b1547602fc44f6da0a5e755ab3a7ef"
|
"GUID:a0b1547602fc44f6da0a5e755ab3a7ef",
|
||||||
|
"GUID:6a0a834eb41764f12ba55c3fb04a40cb",
|
||||||
|
"GUID:b4c9f7fbf1e144933a1797dc208ece5f"
|
||||||
],
|
],
|
||||||
"includePlatforms": [],
|
"includePlatforms": [],
|
||||||
"excludePlatforms": [],
|
"excludePlatforms": [],
|
||||||
|
|||||||
@@ -0,0 +1,63 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using Darkmatter.Core;
|
||||||
|
using Darkmatter.Core.Contracts.Services.Analytics;
|
||||||
|
using Darkmatter.Core.Data.Signals.Features.AppBoot;
|
||||||
|
using Darkmatter.Core.Data.Signals.Features.Capture;
|
||||||
|
using Darkmatter.Core.Data.Signals.Features.Drawing;
|
||||||
|
using Darkmatter.Core.Data.Signals.Features.GameplayFlow;
|
||||||
|
using Darkmatter.Core.Data.Signals.Features.MainMenu;
|
||||||
|
using Darkmatter.Core.Data.Signals.Features.ShapeBuilder;
|
||||||
|
using Darkmatter.Libs.Observer;
|
||||||
|
using VContainer.Unity;
|
||||||
|
|
||||||
|
namespace Darkmatter.Services.Analytics
|
||||||
|
{
|
||||||
|
public sealed class AnalyticsTracker : IStartable, IDisposable
|
||||||
|
{
|
||||||
|
private readonly IEventBus _bus;
|
||||||
|
private readonly IAnalyticsService _analytics;
|
||||||
|
private readonly List<IDisposable> _subs = new();
|
||||||
|
|
||||||
|
public AnalyticsTracker(IEventBus bus, IAnalyticsService analytics)
|
||||||
|
{
|
||||||
|
_bus = bus;
|
||||||
|
_analytics = analytics;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Start()
|
||||||
|
{
|
||||||
|
_subs.Add(_bus.Subscribe<IntroCompletedSignal>(_ => _analytics.LogEvent("intro_completed")));
|
||||||
|
_subs.Add(_bus.Subscribe<PlayBtnClickedSignal>(_ => _analytics.LogEvent("play_clicked")));
|
||||||
|
_subs.Add(_bus.Subscribe<OpenColorBookSignal>(_ => _analytics.LogEvent("colorbook_opened")));
|
||||||
|
_subs.Add(_bus.Subscribe<OpenArtBookSignal>(_ => _analytics.LogEvent("artbook_opened")));
|
||||||
|
_subs.Add(_bus.Subscribe<ReturnToMainMenuSignal>(_ => _analytics.LogEvent("main_menu_returned")));
|
||||||
|
|
||||||
|
_subs.Add(_bus.Subscribe<DrawingSelectedSignal>(s =>
|
||||||
|
_analytics.LogEvent("drawing_selected", "template_id", s.TemplateId)));
|
||||||
|
|
||||||
|
_subs.Add(_bus.Subscribe<ShapeBuilderStartedSignal>(s =>
|
||||||
|
_analytics.LogEvent("shape_builder_started", "template_id", s.TemplateId)));
|
||||||
|
|
||||||
|
_subs.Add(_bus.Subscribe<ShapeAssembledSignal>(s =>
|
||||||
|
_analytics.LogEvent("shape_assembled", "template_id", s.TemplateId)));
|
||||||
|
|
||||||
|
_subs.Add(_bus.Subscribe<DrawingCompletedSignal>(s => _analytics.LogEvent("drawing_completed",
|
||||||
|
new Dictionary<string, object>
|
||||||
|
{
|
||||||
|
["template_id"] = s.TemplateId,
|
||||||
|
["completion_count"] = s.CompletionCount,
|
||||||
|
})));
|
||||||
|
|
||||||
|
_subs.Add(_bus.Subscribe<GallerySaveStartedSignal>(_ => _analytics.LogEvent("gallery_save_started")));
|
||||||
|
_subs.Add(_bus.Subscribe<GallerySaveCompletedSignal>(s =>
|
||||||
|
_analytics.LogEvent("gallery_save_completed", "success", s.Success ? "true" : "false")));
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Dispose()
|
||||||
|
{
|
||||||
|
foreach (var s in _subs) s?.Dispose();
|
||||||
|
_subs.Clear();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,2 @@
|
|||||||
|
fileFormatVersion: 2
|
||||||
|
guid: 5ad16bfd960ac4a7391ffffcc6e7bd59
|
||||||
@@ -1,42 +1,100 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
using System.Threading;
|
using System.Threading;
|
||||||
using Cysharp.Threading.Tasks;
|
using Cysharp.Threading.Tasks;
|
||||||
|
using Darkmatter.Core.Contracts.Services.Analytics;
|
||||||
|
using Firebase;
|
||||||
|
using Firebase.Analytics;
|
||||||
using Firebase.Crashlytics;
|
using Firebase.Crashlytics;
|
||||||
|
using UnityEngine;
|
||||||
using VContainer.Unity;
|
using VContainer.Unity;
|
||||||
|
|
||||||
namespace Darkmatter.Services.Analytics
|
namespace Darkmatter.Services.Analytics
|
||||||
{
|
{
|
||||||
public class FirebaseAnalyticsSystem : IAsyncStartable
|
public class FirebaseAnalyticsSystem : IAnalyticsService, IAsyncStartable
|
||||||
{
|
{
|
||||||
public async UniTask StartAsync(CancellationToken cancellation = new CancellationToken())
|
private bool _ready;
|
||||||
|
private bool _failed;
|
||||||
|
private readonly Queue<Action> _pending = new();
|
||||||
|
|
||||||
|
public async UniTask StartAsync(CancellationToken cancellation = default)
|
||||||
{
|
{
|
||||||
await Firebase.FirebaseApp.CheckAndFixDependenciesAsync().ContinueWith(task =>
|
DependencyStatus status;
|
||||||
|
try
|
||||||
{
|
{
|
||||||
var dependencyStatus = task.Result;
|
status = await FirebaseApp.CheckAndFixDependenciesAsync().AsUniTask();
|
||||||
if (dependencyStatus == Firebase.DependencyStatus.Available)
|
}
|
||||||
|
catch (Exception e)
|
||||||
{
|
{
|
||||||
// Create and hold a reference to your FirebaseApp,
|
Debug.LogError($"[FirebaseAnalytics] Init failed: {e}");
|
||||||
// where app is a Firebase.FirebaseApp property of your application class.
|
_failed = true;
|
||||||
// Crashlytics will use the DefaultInstance, as well;
|
_pending.Clear();
|
||||||
// this ensures that Crashlytics is initialized.
|
return;
|
||||||
Firebase.FirebaseApp app = Firebase.FirebaseApp.DefaultInstance;
|
}
|
||||||
|
|
||||||
|
if (status != DependencyStatus.Available)
|
||||||
|
{
|
||||||
|
Debug.LogError($"[FirebaseAnalytics] Deps unavailable: {status}");
|
||||||
|
_failed = true;
|
||||||
|
_pending.Clear();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
_ = FirebaseApp.DefaultInstance;
|
||||||
#if DEVELOPMENT_BUILD
|
#if DEVELOPMENT_BUILD
|
||||||
Firebase.Crashlytics.Crashlytics.SetCustomKey("environment", "dev");
|
Crashlytics.SetCustomKey("environment", "dev");
|
||||||
#else
|
#else
|
||||||
Firebase.Crashlytics.Crashlytics.SetCustomKey("environment", "prod");
|
Crashlytics.SetCustomKey("environment", "prod");
|
||||||
#endif
|
#endif
|
||||||
// When this property is set to true, Crashlytics will report all
|
|
||||||
// uncaught exceptions as fatal events. This is the recommended behavior.
|
|
||||||
Crashlytics.ReportUncaughtExceptionsAsFatal = true;
|
Crashlytics.ReportUncaughtExceptionsAsFatal = true;
|
||||||
|
|
||||||
// Set a flag here for indicating that your project is ready to use Firebase.
|
_ready = true;
|
||||||
}
|
while (_pending.Count > 0)
|
||||||
else
|
|
||||||
{
|
{
|
||||||
UnityEngine.Debug.LogError(System.String.Format(
|
try { _pending.Dequeue().Invoke(); }
|
||||||
"Could not resolve all Firebase dependencies: {0}", dependencyStatus));
|
catch (Exception e) { Debug.LogError($"[FirebaseAnalytics] Queued event failed: {e}"); }
|
||||||
// Firebase Unity SDK is not safe to use here.
|
|
||||||
}
|
|
||||||
}, cancellation);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void LogEvent(string name) =>
|
||||||
|
Run(() => FirebaseAnalytics.LogEvent(name));
|
||||||
|
|
||||||
|
public void LogEvent(string name, string paramName, string paramValue) =>
|
||||||
|
Run(() => FirebaseAnalytics.LogEvent(name, paramName, paramValue ?? string.Empty));
|
||||||
|
|
||||||
|
public void LogEvent(string name, IReadOnlyDictionary<string, object> parameters)
|
||||||
|
{
|
||||||
|
if (parameters == null || parameters.Count == 0)
|
||||||
|
{
|
||||||
|
LogEvent(name);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
var arr = new Parameter[parameters.Count];
|
||||||
|
int i = 0;
|
||||||
|
foreach (var kv in parameters) arr[i++] = ToParameter(kv.Key, kv.Value);
|
||||||
|
Run(() => FirebaseAnalytics.LogEvent(name, arr));
|
||||||
|
}
|
||||||
|
|
||||||
|
public void SetUserProperty(string name, string value) =>
|
||||||
|
Run(() => FirebaseAnalytics.SetUserProperty(name, value ?? string.Empty));
|
||||||
|
|
||||||
|
private void Run(Action action)
|
||||||
|
{
|
||||||
|
if (_failed) return;
|
||||||
|
if (_ready) { try { action(); } catch (Exception e) { Debug.LogError($"[FirebaseAnalytics] Event failed: {e}"); } }
|
||||||
|
else _pending.Enqueue(action);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static Parameter ToParameter(string key, object value) => value switch
|
||||||
|
{
|
||||||
|
null => new Parameter(key, string.Empty),
|
||||||
|
long l => new Parameter(key, l),
|
||||||
|
int i => new Parameter(key, i),
|
||||||
|
double d => new Parameter(key, d),
|
||||||
|
float f => new Parameter(key, (double)f),
|
||||||
|
bool b => new Parameter(key, b ? 1L : 0L),
|
||||||
|
_ => new Parameter(key, value.ToString())
|
||||||
|
};
|
||||||
|
}
|
||||||
}
|
}
|
||||||
BIN
Assets/Darkmatter/Content/.DS_Store
vendored
BIN
Assets/Darkmatter/Content/.DS_Store
vendored
Binary file not shown.
BIN
Assets/Darkmatter/Content/Colorbook UI/.DS_Store
vendored
BIN
Assets/Darkmatter/Content/Colorbook UI/.DS_Store
vendored
Binary file not shown.
File diff suppressed because one or more lines are too long
BIN
Assets/Darkmatter/Content/Sprites/MiniGame/DrawingGame/.DS_Store
vendored
Normal file
BIN
Assets/Darkmatter/Content/Sprites/MiniGame/DrawingGame/.DS_Store
vendored
Normal file
Binary file not shown.
BIN
Assets/Darkmatter/Content/Sprites/MiniGame/DrawingGame/Artbook UI Sprites/.DS_Store
vendored
Normal file
BIN
Assets/Darkmatter/Content/Sprites/MiniGame/DrawingGame/Artbook UI Sprites/.DS_Store
vendored
Normal file
Binary file not shown.
Binary file not shown.
|
Before Width: | Height: | Size: 459 KiB After Width: | Height: | Size: 1.1 MiB |
@@ -22,7 +22,7 @@ MonoBehaviour:
|
|||||||
- {r: 1, g: 1, b: 1, a: 1}
|
- {r: 1, g: 1, b: 1, a: 1}
|
||||||
- {r: 0.05724919, g: 1, b: 0, a: 1}
|
- {r: 0.05724919, g: 1, b: 0, a: 1}
|
||||||
- {r: 0, g: 0, b: 0, a: 1}
|
- {r: 0, g: 0, b: 0, a: 1}
|
||||||
- {r: 0, g: 0.6845894, b: 1, a: 1}
|
- {r: 0, g: 0.9229766, b: 0.9622642, a: 1}
|
||||||
- {r: 1, g: 0, b: 0.7162385, a: 1}
|
- {r: 1, g: 0, b: 0.7162385, a: 1}
|
||||||
- {r: 0.3857726, g: 0, b: 1, a: 1}
|
- {r: 0.3857726, g: 0, b: 1, a: 1}
|
||||||
- {r: 0.5188679, g: 0.38189316, b: 0.30593628, a: 1}
|
- {r: 0.5188679, g: 0.38189316, b: 0.30593628, a: 1}
|
||||||
|
|||||||
@@ -15,7 +15,7 @@ EditorBuildSettings:
|
|||||||
path: Assets/Darkmatter/Scenes/Colorbook.unity
|
path: Assets/Darkmatter/Scenes/Colorbook.unity
|
||||||
guid: 145ae55f6571bfe4fbadaefb863ba69d
|
guid: 145ae55f6571bfe4fbadaefb863ba69d
|
||||||
- enabled: 1
|
- enabled: 1
|
||||||
path: Assets/Darkmatter/Scenes/GamePlay.unity
|
path: Assets/Darkmatter/Scenes/Gameplay.unity
|
||||||
guid: e5f73f24e812e4a98b4c17d533fd3d6d
|
guid: e5f73f24e812e4a98b4c17d533fd3d6d
|
||||||
m_configObjects:
|
m_configObjects:
|
||||||
com.unity.addressableassets: {fileID: 11400000, guid: 732f53b1f9e534015be7dcd28d7032bd, type: 2}
|
com.unity.addressableassets: {fileID: 11400000, guid: 732f53b1f9e534015be7dcd28d7032bd, type: 2}
|
||||||
|
|||||||
Reference in New Issue
Block a user