com.amanotes.gdk 0.2.66 → 0.2.68
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +19 -0
- package/Editor/Extra/GDKAutoUpdateAdapter.cs +67 -0
- package/Editor/Extra/GDKAutoUpdateAdapter.cs.meta +11 -0
- package/Extra/AmaGDKInstaller.unitypackage +0 -0
- package/Extra/CheckDiskSpace.unitypackage +0 -0
- package/Extra/ForceUpdate.unitypackage +0 -0
- package/Extra/GoogleCMP.unitypackage +0 -0
- package/Extra/LegacyGDKUpdateHelper.unitypackage +0 -0
- package/Extra/LegacyGDKUpdateHelper.unitypackage.meta +7 -0
- package/Extra/PostProcessor.unitypackage +0 -0
- package/Packages/AmaGDKConfig.unitypackage +0 -0
- package/Packages/AmaGDKExample.unitypackage +0 -0
- package/Packages/AmaGDKTest.unitypackage +0 -0
- package/Packages/AppsFlyerAdapter.PurchaseConnector.unitypackage +0 -0
- package/Packages/AppsFlyerAdapter.unitypackage +0 -0
- package/Packages/FirebaseAnalyticsAdapter.unitypackage +0 -0
- package/Packages/FirebaseRemoteConfigAdapter.unitypackage +0 -0
- package/Packages/IronSourceAdapter.unitypackage +0 -0
- package/Packages/RevenueCatAdapter.unitypackage +0 -0
- package/Packages/SqliteAnalyticsAdapter.unitypackage +0 -0
- package/Runtime/Ad/AdExtension.cs +111 -0
- package/Runtime/Ad/AdExtension.cs.meta +3 -0
- package/Runtime/Ad/AdLogic.cs +530 -0
- package/Runtime/Ad/AdLogic.cs.meta +3 -0
- package/Runtime/Ad/AdModuleConfig.cs +39 -0
- package/Runtime/Ad/AdModuleConfig.cs.meta +3 -0
- package/Runtime/Ad/AdShowContext.cs +43 -0
- package/Runtime/Ad/AdShowContext.cs.meta +3 -0
- package/Runtime/Ad/AmaGDK.Ads.cs +383 -0
- package/Runtime/Ad.meta +8 -0
- package/Runtime/AmaGDK.Analytics.cs +20 -1
- package/Runtime/AmaGDK.Device.cs +105 -0
- package/Runtime/AmaGDK.Device.cs.meta +3 -0
- package/Runtime/AmaGDK.Mono.cs +0 -1
- package/Runtime/AmaGDK.cs +6 -2
- package/Runtime/AudioToolkit/AmaGDK.Audio.cs +16 -0
- package/Runtime/AudioToolkit/Plugins/Android/GDKAudioDeviceDetector.java +1 -1
- package/Runtime/Fps/AmaFPS.Utils.cs +44 -0
- package/Runtime/Fps/AmaFPS.Utils.cs.meta +3 -0
- package/Runtime/Fps/AmaFPS.cs +197 -0
- package/Runtime/Fps/AmaFPS.cs.meta +11 -0
- package/Runtime/Fps/AmaFPSVisualizer.cs +246 -0
- package/Runtime/Fps/AmaFPSVisualizer.cs.meta +11 -0
- package/Runtime/Fps/BollingerBands.cs +99 -0
- package/Runtime/Fps/BollingerBands.cs.meta +11 -0
- package/Runtime/Fps/FPSVisualizer.prefab +406 -0
- package/Runtime/Fps/FPSVisualizer.prefab.meta +7 -0
- package/Runtime/Fps/FrameRecorder.cs +172 -0
- package/Runtime/Fps/FrameRecorder.cs.meta +3 -0
- package/Runtime/Fps.meta +8 -0
- package/package.json +1 -1
- package/Runtime/AmaGDK.Ads.cs +0 -1077
- /package/Runtime/{AmaGDK.Ads.cs.meta → Ad/AmaGDK.Ads.cs.meta} +0 -0
|
@@ -0,0 +1,197 @@
|
|
|
1
|
+
using System;
|
|
2
|
+
using System.Collections.Generic;
|
|
3
|
+
using Amanotes.Core.Internal;
|
|
4
|
+
using static Amanotes.Core.Internal.Logging;
|
|
5
|
+
using UnityEngine;
|
|
6
|
+
using UnityEngine.Events;
|
|
7
|
+
|
|
8
|
+
namespace Amanotes.Core.Internal
|
|
9
|
+
{
|
|
10
|
+
public partial class ConfigAsset
|
|
11
|
+
{
|
|
12
|
+
[SerializeField]
|
|
13
|
+
public FPSConfig fpsConfig;
|
|
14
|
+
}
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
namespace Amanotes.Core
|
|
18
|
+
{
|
|
19
|
+
public partial class AmaGDK
|
|
20
|
+
{
|
|
21
|
+
public static readonly AmaFPS FPS = new AmaFPS();
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
[Serializable]
|
|
26
|
+
public class FPSConfig
|
|
27
|
+
{
|
|
28
|
+
[Tooltip("Enable this to always record FPS for the app session. This allows developers to get the current FPS and current average FPS at any time.")]
|
|
29
|
+
public bool enableRealtimeFPS = false;
|
|
30
|
+
|
|
31
|
+
[Tooltip("The number of frames over which FPS is calculated. The FPS will be averaged after every 'frameGroup' frames.")]
|
|
32
|
+
[Range(1, 60)]
|
|
33
|
+
public int frameGroup = 20;
|
|
34
|
+
|
|
35
|
+
[Header("Lagging Tolerance")]
|
|
36
|
+
[Tooltip("The size of the sliding window used to calculate the Simple Moving Average (SMA) of the FPS.")]
|
|
37
|
+
[Range(10, 100)]
|
|
38
|
+
public int windowSize = 15;
|
|
39
|
+
|
|
40
|
+
[Tooltip("The allowed deviation from the SMA to detect an FPS drop.")]
|
|
41
|
+
[Range(0f, 0.3f)]
|
|
42
|
+
public float deviation = 0.1f;
|
|
43
|
+
|
|
44
|
+
[Tooltip("Number of frames to skip after OnApplicationFocus to avoid false alarms.")]
|
|
45
|
+
[Range(0, 60)]
|
|
46
|
+
public int skipFrameFocus = 10;
|
|
47
|
+
|
|
48
|
+
[Header("Callback")]
|
|
49
|
+
[Tooltip("This callback is invoked when an FPS drop is detected.")]
|
|
50
|
+
public UnityEvent onFrameDrop = new UnityEvent();
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
public partial class AmaFPS // public API
|
|
54
|
+
{
|
|
55
|
+
|
|
56
|
+
public float CurrentFPS => _realtime?.lastFPS ?? 0;
|
|
57
|
+
public float AverageFPS => _realtime?.avgFPS ?? 0;
|
|
58
|
+
public float MinFPS => _realtime?.minFPS ?? 0;
|
|
59
|
+
public float MaxFPS => _realtime?.maxFPS ?? 0;
|
|
60
|
+
public Action<string, Dictionary<string, object>> LogEventHook;
|
|
61
|
+
|
|
62
|
+
private bool _isAppReady = false;
|
|
63
|
+
private int _playCount = 0;
|
|
64
|
+
|
|
65
|
+
public void TrackLaunchTime()
|
|
66
|
+
{
|
|
67
|
+
if (_isAppReady)
|
|
68
|
+
{
|
|
69
|
+
Log("TrackAppReady() being called multiple time!");
|
|
70
|
+
return;
|
|
71
|
+
}
|
|
72
|
+
_isAppReady = true;
|
|
73
|
+
|
|
74
|
+
var dict = new Dictionary<string, object>()
|
|
75
|
+
{
|
|
76
|
+
{"loading_time", Time.realtimeSinceStartup},
|
|
77
|
+
{"session", AmaGDK.User.Session},
|
|
78
|
+
{"device_name", SystemInfo.deviceModel},
|
|
79
|
+
{"device_os_version", SystemInfo.operatingSystem},
|
|
80
|
+
|
|
81
|
+
// Update
|
|
82
|
+
{"game_time", Time.time},
|
|
83
|
+
};
|
|
84
|
+
|
|
85
|
+
Utils.InjectDeviceInfo(dict);
|
|
86
|
+
Utils.InjectDeviceStatus(dict);
|
|
87
|
+
|
|
88
|
+
LogEvent("pm_launch_time", dict);
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
public void StartRecordFPS(string context, Dictionary<string, object> userData = null)
|
|
92
|
+
{
|
|
93
|
+
_recorder ??= new FrameRecorder(_config ?? AmaGDK.Config.fpsConfig);
|
|
94
|
+
if (_recorder.isRecording)
|
|
95
|
+
{
|
|
96
|
+
LogWarning("Not yet support - Start multiple recorders at the same time! Please stop the previous session first!");
|
|
97
|
+
return;
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
_recorder.Start(context, userData);
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
public Dictionary<string, object> StopRecordFPS(bool logEvent = true)
|
|
104
|
+
{
|
|
105
|
+
if (_recorder == null || !_recorder.isRecording)
|
|
106
|
+
{
|
|
107
|
+
LogWarning("No tracking session found!");
|
|
108
|
+
return null;
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
var data = _recorder.Stop();
|
|
112
|
+
if (logEvent) LogEvent("fps_measurement", data);
|
|
113
|
+
return data;
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
private void LogEvent(string eventName, Dictionary<string, object> parameters)
|
|
117
|
+
{
|
|
118
|
+
if (LogEventHook == null)
|
|
119
|
+
{
|
|
120
|
+
AmaGDK.Analytics.LogEvent(eventName, parameters);
|
|
121
|
+
return;
|
|
122
|
+
}
|
|
123
|
+
LogEventHook(eventName, parameters);
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
public partial class AmaFPS: IOnApplicationFocus, IOnApplicationPause, IOnFrameUpdate // Internal logic
|
|
128
|
+
{
|
|
129
|
+
private FrameRecorder _recorder;
|
|
130
|
+
private FrameRecorder _realtime;
|
|
131
|
+
private int _skipFrames = 0;
|
|
132
|
+
private FPSConfig _config;
|
|
133
|
+
|
|
134
|
+
internal AmaFPS()
|
|
135
|
+
{
|
|
136
|
+
AmaGDK.SetCallback_OnGDKInit(OnGDKInit);
|
|
137
|
+
AmaGDK.unityCallbacks.AddObserver(this);
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
internal AmaFPS(FPSConfig config)
|
|
141
|
+
{
|
|
142
|
+
// Constructor for unit test
|
|
143
|
+
_config = config;
|
|
144
|
+
_realtime = new FrameRecorder(config);
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
private void OnGDKInit()
|
|
148
|
+
{
|
|
149
|
+
_config = AmaGDK.Config.fpsConfig;
|
|
150
|
+
_realtime ??= new FrameRecorder(_config);
|
|
151
|
+
|
|
152
|
+
_realtime.bands.onFPSDrop -= OnFrameDrop;
|
|
153
|
+
_realtime.bands.onFPSDrop += OnFrameDrop;
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
private void OnFrameDrop()
|
|
157
|
+
{
|
|
158
|
+
if (_config.onFrameDrop.GetPersistentEventCount() > 0)
|
|
159
|
+
{
|
|
160
|
+
_config.onFrameDrop.Invoke();
|
|
161
|
+
}
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
public void OnFrameUpdate()
|
|
165
|
+
{
|
|
166
|
+
UpdateFrame(Time.unscaledDeltaTime);
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
internal void UpdateFrame(float unscaledDeltaTime)
|
|
170
|
+
{
|
|
171
|
+
if (unscaledDeltaTime <= 1 / 1200f) unscaledDeltaTime = 1 / 1200f; // prevent the case when unscaledDeltaTime == 0
|
|
172
|
+
|
|
173
|
+
if (_skipFrames > 0)
|
|
174
|
+
{
|
|
175
|
+
_skipFrames--;
|
|
176
|
+
return;
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
if (_realtime != null && _config.enableRealtimeFPS) _realtime.UpdateFrame(unscaledDeltaTime);
|
|
180
|
+
|
|
181
|
+
if (_recorder != null && _recorder.isRecording)
|
|
182
|
+
{
|
|
183
|
+
_recorder.UpdateFrame(unscaledDeltaTime);
|
|
184
|
+
}
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
public void OnApplicationFocus(bool hasFocus)
|
|
188
|
+
{
|
|
189
|
+
_skipFrames = _config?.skipFrameFocus ?? 0;
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
public void OnApplicationPause(bool pauseStatus)
|
|
193
|
+
{
|
|
194
|
+
_skipFrames = _config?.skipFrameFocus ?? 0;
|
|
195
|
+
}
|
|
196
|
+
}
|
|
197
|
+
}
|
|
@@ -0,0 +1,246 @@
|
|
|
1
|
+
using System;
|
|
2
|
+
using System.Collections.Generic;
|
|
3
|
+
using UnityEngine;
|
|
4
|
+
using UnityEngine.Profiling;
|
|
5
|
+
using UnityEngine.UI;
|
|
6
|
+
using static Amanotes.Core.Internal.Logging;
|
|
7
|
+
|
|
8
|
+
namespace Amanotes.Core
|
|
9
|
+
{
|
|
10
|
+
|
|
11
|
+
[RequireComponent(typeof(RectTransform))]
|
|
12
|
+
[RequireComponent(typeof(CanvasRenderer))]
|
|
13
|
+
public class AmaFPSVisualizer : Graphic
|
|
14
|
+
{
|
|
15
|
+
[Serializable]
|
|
16
|
+
private class FlashOnDrop
|
|
17
|
+
{
|
|
18
|
+
public bool enabled = true;
|
|
19
|
+
public Color flashColor = new Color(1, 0, 0, 0.5f);
|
|
20
|
+
[Range(1f, 10f)] public float flashingSpeed = 10f;
|
|
21
|
+
|
|
22
|
+
public Image flashImage;
|
|
23
|
+
private float _alpha = 0;
|
|
24
|
+
|
|
25
|
+
public void OnFrameDrop()
|
|
26
|
+
{
|
|
27
|
+
_alpha = flashColor.a;
|
|
28
|
+
flashImage.color = flashColor;
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
public void Update()
|
|
32
|
+
{
|
|
33
|
+
float dAlpha = flashingSpeed * Time.deltaTime;
|
|
34
|
+
_alpha = Mathf.Max(0, _alpha - dAlpha);
|
|
35
|
+
|
|
36
|
+
Color c = flashColor;
|
|
37
|
+
c.a = _alpha;
|
|
38
|
+
flashImage.color = c;
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
[Serializable]
|
|
43
|
+
private class FPSTextUpdate
|
|
44
|
+
{
|
|
45
|
+
private static readonly Dictionary<int, string> intMap = new Dictionary<int, string>();
|
|
46
|
+
private static string GetString(float value)
|
|
47
|
+
{
|
|
48
|
+
Profiler.BeginSample("FPSTextUpdate.GetString");
|
|
49
|
+
int intValue = Mathf.RoundToInt(value * 10);
|
|
50
|
+
if (intMap.TryGetValue(intValue, out string result))
|
|
51
|
+
{
|
|
52
|
+
Profiler.EndSample();
|
|
53
|
+
return result;
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
result = $"{(intValue/10f):F1}";
|
|
57
|
+
intMap.Add(intValue, result);
|
|
58
|
+
Profiler.EndSample();
|
|
59
|
+
return result;
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
public bool enabled = true;
|
|
63
|
+
public GameObject parent = null;
|
|
64
|
+
|
|
65
|
+
public Text currentFPS;
|
|
66
|
+
private int frame;
|
|
67
|
+
|
|
68
|
+
public void Update(float fps)
|
|
69
|
+
{
|
|
70
|
+
if (frame-- > 0) return;
|
|
71
|
+
currentFPS.text = GetString(fps);
|
|
72
|
+
frame = 60;
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
struct FPSVertex
|
|
77
|
+
{
|
|
78
|
+
public float fps;
|
|
79
|
+
public int colorIndex;
|
|
80
|
+
public Vector3 position;
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
[Serializable]
|
|
84
|
+
private class FPSGraph : FrameRecorder
|
|
85
|
+
{
|
|
86
|
+
const int RESOLUTION = 64;
|
|
87
|
+
public bool enabled = true;
|
|
88
|
+
public Graphic graphic = null;
|
|
89
|
+
|
|
90
|
+
public int minFPS = 15;
|
|
91
|
+
public int maxFPS = 60;
|
|
92
|
+
public int goodFPS = 55;
|
|
93
|
+
public int acceptableFPS = 45;
|
|
94
|
+
public int badFPS = 30;
|
|
95
|
+
|
|
96
|
+
public Color[] colors = new Color[]{
|
|
97
|
+
Color.red, // min -> bad
|
|
98
|
+
new Color(1f, 0.65f, 0f), // bad -> ok
|
|
99
|
+
Color.yellow, // ok --> good
|
|
100
|
+
Color.green, // very good
|
|
101
|
+
};
|
|
102
|
+
|
|
103
|
+
private readonly float[] fpsHistory = new float[RESOLUTION];
|
|
104
|
+
private int vCount = 0;
|
|
105
|
+
|
|
106
|
+
public void Clear()
|
|
107
|
+
{
|
|
108
|
+
vCount = 0;
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
protected override void UpdateGroupFrame(){
|
|
112
|
+
var hIndex = vCount % RESOLUTION;
|
|
113
|
+
fpsHistory[hIndex] = lastFPS;
|
|
114
|
+
vCount++;
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
public void PopulateMesh(VertexHelper vh)
|
|
118
|
+
{
|
|
119
|
+
var rect = ((RectTransform)graphic.transform).rect;
|
|
120
|
+
var barW = rect.width / (RESOLUTION-1);
|
|
121
|
+
var barH = rect.height;
|
|
122
|
+
|
|
123
|
+
var barX = vCount < RESOLUTION ? (RESOLUTION - vCount) * barW : 0;
|
|
124
|
+
var stIndex = vCount <= RESOLUTION ? 0 : (vCount % RESOLUTION);
|
|
125
|
+
var nVertex = vCount <= RESOLUTION ? vCount : RESOLUTION;
|
|
126
|
+
|
|
127
|
+
for (var i = 0; i < nVertex; i++)
|
|
128
|
+
{
|
|
129
|
+
var idx = (i + stIndex) % RESOLUTION;
|
|
130
|
+
var fps = fpsHistory[idx];
|
|
131
|
+
var h = fps <= minFPS ? 0 :
|
|
132
|
+
fps >= maxFPS ? 1 : (fps - minFPS) / (maxFPS - minFPS);
|
|
133
|
+
|
|
134
|
+
var v0 = new Vector3(barX, 0, 0);
|
|
135
|
+
var v1 = new Vector3(barX, h * barH, 0);
|
|
136
|
+
var c1 = colors[
|
|
137
|
+
fps <= badFPS ? 0 :
|
|
138
|
+
fps <= acceptableFPS ? 1 :
|
|
139
|
+
fps <= goodFPS ? 2 : 3
|
|
140
|
+
];
|
|
141
|
+
var c0 = c1;
|
|
142
|
+
c0.a = 0;
|
|
143
|
+
|
|
144
|
+
// Add 2 vertices
|
|
145
|
+
vh.AddVert(v0, c0, Vector2.zero);
|
|
146
|
+
vh.AddVert(v1, c1, Vector2.zero);
|
|
147
|
+
|
|
148
|
+
if (i > 0)
|
|
149
|
+
{
|
|
150
|
+
var vIndex = vh.currentVertCount - 2;
|
|
151
|
+
vh.AddTriangle(vIndex - 2, vIndex - 1, vIndex + 1);
|
|
152
|
+
vh.AddTriangle(vIndex - 2, vIndex + 1, vIndex);
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
barX += barW;
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
AddHorzLine(vh, rect.width, barH * ((goodFPS-minFPS) / (float)(maxFPS-minFPS)), colors[2], 2f);
|
|
159
|
+
AddHorzLine(vh, rect.width, barH * ((acceptableFPS-minFPS) / (float)(maxFPS-minFPS)), colors[1], 2f);
|
|
160
|
+
AddHorzLine(vh, rect.width, barH * ((badFPS-minFPS) / (float)(maxFPS-minFPS)), colors[0], 2f);
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
void AddHorzLine(VertexHelper vh, float w, float h, Color color, float thickness = 1f)
|
|
164
|
+
{
|
|
165
|
+
var v0 = new Vector3(0, h, 0);
|
|
166
|
+
var v1 = new Vector3(w, h, 0);
|
|
167
|
+
var v2 = new Vector3(w, h+thickness, 0);
|
|
168
|
+
var v3 = new Vector3(0, h+thickness, 0);
|
|
169
|
+
|
|
170
|
+
var vIndex = vh.currentVertCount;
|
|
171
|
+
|
|
172
|
+
vh.AddVert(v0, color, new Vector2(0, 0));
|
|
173
|
+
vh.AddVert(v1, color, new Vector2(0, 0));
|
|
174
|
+
vh.AddVert(v2, color, new Vector2(0, 0));
|
|
175
|
+
vh.AddVert(v3, color, new Vector2(0, 0));
|
|
176
|
+
|
|
177
|
+
vh.AddTriangle(vIndex, vIndex+1, vIndex+2);
|
|
178
|
+
vh.AddTriangle(vIndex+2, vIndex+3, vIndex);
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
public FPSGraph(FPSConfig config) : base(config)
|
|
182
|
+
{
|
|
183
|
+
}
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
[SerializeField] private FlashOnDrop flashOnDropFrame = new FlashOnDrop();
|
|
187
|
+
[SerializeField] private FPSTextUpdate textUpdate = new FPSTextUpdate();
|
|
188
|
+
|
|
189
|
+
private FPSGraph graph;
|
|
190
|
+
|
|
191
|
+
protected override void Awake()
|
|
192
|
+
{
|
|
193
|
+
flashOnDropFrame.flashImage.enabled = flashOnDropFrame.enabled;
|
|
194
|
+
textUpdate.parent.SetActive(textUpdate.enabled);
|
|
195
|
+
|
|
196
|
+
graph = new FPSGraph(AmaGDK.Config.fpsConfig)
|
|
197
|
+
{
|
|
198
|
+
graphic = GetComponent<Graphic>()
|
|
199
|
+
};
|
|
200
|
+
|
|
201
|
+
Application.targetFrameRate = Screen.currentResolution.refreshRate;
|
|
202
|
+
Log($"Target FrameRate: {Application.targetFrameRate}");
|
|
203
|
+
}
|
|
204
|
+
|
|
205
|
+
protected override void Start()
|
|
206
|
+
{
|
|
207
|
+
var rect = Screen.safeArea;
|
|
208
|
+
var trans = transform as RectTransform;
|
|
209
|
+
var transRect = trans.rect;
|
|
210
|
+
trans.anchoredPosition = new Vector2(rect.x / rect.width * transRect.width, -rect.y / rect.height * transRect.height);
|
|
211
|
+
}
|
|
212
|
+
|
|
213
|
+
public void OnFrameDrop()
|
|
214
|
+
{
|
|
215
|
+
flashOnDropFrame.OnFrameDrop();
|
|
216
|
+
}
|
|
217
|
+
|
|
218
|
+
private void Update()
|
|
219
|
+
{
|
|
220
|
+
if (!Application.isPlaying) return;
|
|
221
|
+
Profiler.BeginSample("AmaFPSVisualiser.Update()");
|
|
222
|
+
{
|
|
223
|
+
if (flashOnDropFrame.enabled) flashOnDropFrame.Update();
|
|
224
|
+
if (textUpdate.enabled) textUpdate.Update(1f/Time.unscaledDeltaTime);
|
|
225
|
+
if (graph != null && graph.enabled)
|
|
226
|
+
{
|
|
227
|
+
graph.UpdateFrame(Time.unscaledDeltaTime);
|
|
228
|
+
Profiler.BeginSample("SetVerticesDirty()");
|
|
229
|
+
{
|
|
230
|
+
SetVerticesDirty();
|
|
231
|
+
}
|
|
232
|
+
Profiler.EndSample();
|
|
233
|
+
}
|
|
234
|
+
}
|
|
235
|
+
Profiler.EndSample();
|
|
236
|
+
}
|
|
237
|
+
|
|
238
|
+
protected override void OnPopulateMesh(VertexHelper vh)
|
|
239
|
+
{
|
|
240
|
+
vh.Clear();
|
|
241
|
+
|
|
242
|
+
if (graph == null || !graph.enabled) return;
|
|
243
|
+
graph.PopulateMesh(vh);
|
|
244
|
+
}
|
|
245
|
+
}
|
|
246
|
+
}
|
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
using System;
|
|
2
|
+
using Amanotes.Core.Internal;
|
|
3
|
+
|
|
4
|
+
namespace Amanotes.Core
|
|
5
|
+
{
|
|
6
|
+
internal class BollingerBands
|
|
7
|
+
{
|
|
8
|
+
internal event Action onFPSDrop;
|
|
9
|
+
internal int currentDropCount { get; private set; }
|
|
10
|
+
internal int totalDrop { get; private set; }
|
|
11
|
+
internal int isoDrop { get; private set; }
|
|
12
|
+
|
|
13
|
+
private readonly float[] buffer;
|
|
14
|
+
private readonly float tolerance;
|
|
15
|
+
private int bIndex;
|
|
16
|
+
private float sum;
|
|
17
|
+
|
|
18
|
+
internal BollingerBands(int window = 20, float deviation = 0.1f)
|
|
19
|
+
{ // ~10%
|
|
20
|
+
buffer = new float[window];
|
|
21
|
+
tolerance = 1f - deviation;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
internal void Reset(float v)
|
|
25
|
+
{
|
|
26
|
+
for (var i = 0; i < buffer.Length; i++)
|
|
27
|
+
{
|
|
28
|
+
buffer[i] = v;
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
bIndex = 0;
|
|
32
|
+
currentDropCount = 0;
|
|
33
|
+
totalDrop = 0;
|
|
34
|
+
isoDrop = 0;
|
|
35
|
+
_last = v;
|
|
36
|
+
sum = v * buffer.Length;
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
internal float last => _last;
|
|
40
|
+
internal float avg => sum / buffer.Length;
|
|
41
|
+
internal float min => (_min == -1) ? CalculateMinMax()._min : _min;
|
|
42
|
+
internal float max => (_max == -1) ? CalculateMinMax()._max : _max;
|
|
43
|
+
|
|
44
|
+
internal bool Add(float v)
|
|
45
|
+
{
|
|
46
|
+
// update cached min / max
|
|
47
|
+
if (_min != -1 && v < _min) _min = v;
|
|
48
|
+
if (_max != -1 && v > _max) _max = v;
|
|
49
|
+
|
|
50
|
+
float v0 = buffer[bIndex];
|
|
51
|
+
buffer[bIndex] = v;
|
|
52
|
+
sum += v - v0;
|
|
53
|
+
bIndex = (bIndex + 1) % buffer.Length;
|
|
54
|
+
_last = v;
|
|
55
|
+
|
|
56
|
+
// clear cached min / max
|
|
57
|
+
if (v0 == _min) _min = -1;
|
|
58
|
+
if (v0 == _max) _max = -1;
|
|
59
|
+
|
|
60
|
+
float sma = sum / buffer.Length;
|
|
61
|
+
bool isDrop = v < sma * tolerance;
|
|
62
|
+
|
|
63
|
+
if (!isDrop)
|
|
64
|
+
{
|
|
65
|
+
currentDropCount = 0;
|
|
66
|
+
return false;
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
totalDrop++;
|
|
70
|
+
currentDropCount++;
|
|
71
|
+
|
|
72
|
+
if (currentDropCount == 1)
|
|
73
|
+
{
|
|
74
|
+
isoDrop++;
|
|
75
|
+
GDKUtils.SafeInvoke(onFPSDrop);
|
|
76
|
+
}
|
|
77
|
+
return true;
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
private float _min;
|
|
81
|
+
private float _max;
|
|
82
|
+
private float _last;
|
|
83
|
+
|
|
84
|
+
private BollingerBands CalculateMinMax()
|
|
85
|
+
{
|
|
86
|
+
_min = buffer[0];
|
|
87
|
+
_max = _min;
|
|
88
|
+
|
|
89
|
+
for (var i = 1; i < buffer.Length; i++)
|
|
90
|
+
{
|
|
91
|
+
float v = buffer[i];
|
|
92
|
+
if (v < _min) _min = v;
|
|
93
|
+
if (v > _max) _max = v;
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
return this;
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
}
|