Compare commits

...
10 Commits
Author SHA1 Message Date
warlock 9970488938 unity error 2026-08-12 13:45:19 +05:30
warlock c2f4c2f808 migration 2026-07-26 12:31:59 +05:30
warlock 4b2129b944 practice mode integrated to the onboarding tutorial 2026-07-04 00:41:46 +05:30
warlock 2de5a166f6 practice mode 2026-07-02 11:41:57 +05:30
warlock 2651068b50 ping reporting 2026-06-02 14:47:32 +05:30
warlock d62bf9e06b test week rc 2026-05-29 10:02:24 +05:30
warlock 0a1d3c7262 sync 2026-05-27 23:24:40 +05:30
warlock f3e01462c1 not enough rc for rematch 2026-05-19 01:17:02 +05:30
warlock 87301a228f disonncet grace improved 2026-05-17 20:11:42 +05:30
warlock aa924c71dc rematch use the same leave function, added a grace period for connection disconnect 2026-05-17 14:50:28 +05:30
669 changed files with 66527 additions and 212 deletions
+20
View File
@@ -264,12 +264,32 @@ public class CupidSettings
public int waiting_time; public int waiting_time;
public int port_range_min; public int port_range_min;
public int port_range_max; public int port_range_max;
public CupidGameEntry[] games;
/// <summary>RC stake per player for the default match (<c>/settings</c>), in coin units (same as matchmaker <c>entry_fee</c>).</summary> /// <summary>RC stake per player for the default match (<c>/settings</c>), in coin units (same as matchmaker <c>entry_fee</c>).</summary>
public int entry_fee; public int entry_fee;
/// <summary>Optional side-bet or table minimum from matchmaker settings; same units as <see cref="entry_fee"/>.</summary> /// <summary>Optional side-bet or table minimum from matchmaker settings; same units as <see cref="entry_fee"/>.</summary>
public int bet_fee; public int bet_fee;
/// <summary>Winner net RC prize from settings, coin units (same as room <c>rc_prize</c>).</summary> /// <summary>Winner net RC prize from settings, coin units (same as room <c>rc_prize</c>).</summary>
public int rc_prize; public int rc_prize;
public CupidTableSettings table_settings;
}
[System.Serializable]
public class CupidGameEntry
{
public string name;
public string exe;
}
[System.Serializable]
public class CupidTableSettings
{
public string entry_fee;
public string bet_fee;
/// <summary>Minimum client version (e.g. <c>0.99</c>, <c>1.21</c>). Compared to <see cref="Application.version"/>.</summary>
public string version;
public string error_msg;
public string warning_msg;
} }
[System.Serializable] [System.Serializable]
+8
View File
@@ -75,6 +75,14 @@ public class Logger
} }
} }
/// <summary>Writable Logs folder next to match log files (creates if missing).</summary>
public static string GetLogsDirectory()
{
string dir = Path.Combine(ApplicationDirectory, "Logs");
EnsureDirectoryExists(dir);
return dir;
}
public static void SetFilePath(string path){ public static void SetFilePath(string path){
instance.LogFilePath= path; instance.LogFilePath= path;
} }
File diff suppressed because one or more lines are too long
@@ -1647,6 +1647,456 @@ MonoBehaviour:
m_XAdvance: 0 m_XAdvance: 0
m_YAdvance: 0 m_YAdvance: 0
m_FeatureLookupFlags: 10188005 m_FeatureLookupFlags: 10188005
- m_FirstAdjustmentRecord:
m_GlyphIndex: 25
m_GlyphValueRecord:
m_XPlacement: 0
m_YPlacement: 0
m_XAdvance: -2.97
m_YAdvance: 0
m_SecondAdjustmentRecord:
m_GlyphIndex: 5
m_GlyphValueRecord:
m_XPlacement: 0
m_YPlacement: 0
m_XAdvance: 0
m_YAdvance: 0
m_FeatureLookupFlags: 1016088
- m_FirstAdjustmentRecord:
m_GlyphIndex: 25
m_GlyphValueRecord:
m_XPlacement: 0
m_YPlacement: 0
m_XAdvance: -0.45000002
m_YAdvance: 0
m_SecondAdjustmentRecord:
m_GlyphIndex: 6
m_GlyphValueRecord:
m_XPlacement: 0
m_YPlacement: 0
m_XAdvance: 0
m_YAdvance: 0
m_FeatureLookupFlags: 1016088
- m_FirstAdjustmentRecord:
m_GlyphIndex: 25
m_GlyphValueRecord:
m_XPlacement: 0
m_YPlacement: 0
m_XAdvance: -0.45000002
m_YAdvance: 0
m_SecondAdjustmentRecord:
m_GlyphIndex: 8
m_GlyphValueRecord:
m_XPlacement: 0
m_YPlacement: 0
m_XAdvance: 0
m_YAdvance: 0
m_FeatureLookupFlags: 1016088
- m_FirstAdjustmentRecord:
m_GlyphIndex: 25
m_GlyphValueRecord:
m_XPlacement: 0
m_YPlacement: 0
m_XAdvance: -0.45000002
m_YAdvance: 0
m_SecondAdjustmentRecord:
m_GlyphIndex: 9
m_GlyphValueRecord:
m_XPlacement: 0
m_YPlacement: 0
m_XAdvance: 0
m_YAdvance: 0
m_FeatureLookupFlags: 1016088
- m_FirstAdjustmentRecord:
m_GlyphIndex: 25
m_GlyphValueRecord:
m_XPlacement: 0
m_YPlacement: 0
m_XAdvance: -0.45000002
m_YAdvance: 0
m_SecondAdjustmentRecord:
m_GlyphIndex: 10
m_GlyphValueRecord:
m_XPlacement: 0
m_YPlacement: 0
m_XAdvance: 0
m_YAdvance: 0
m_FeatureLookupFlags: 1016088
- m_FirstAdjustmentRecord:
m_GlyphIndex: 25
m_GlyphValueRecord:
m_XPlacement: 0
m_YPlacement: 0
m_XAdvance: -0.45000002
m_YAdvance: 0
m_SecondAdjustmentRecord:
m_GlyphIndex: 12
m_GlyphValueRecord:
m_XPlacement: 0
m_YPlacement: 0
m_XAdvance: 0
m_YAdvance: 0
m_FeatureLookupFlags: 1016088
- m_FirstAdjustmentRecord:
m_GlyphIndex: 25
m_GlyphValueRecord:
m_XPlacement: 0
m_YPlacement: 0
m_XAdvance: -0.45000002
m_YAdvance: 0
m_SecondAdjustmentRecord:
m_GlyphIndex: 13
m_GlyphValueRecord:
m_XPlacement: 0
m_YPlacement: 0
m_XAdvance: 0
m_YAdvance: 0
m_FeatureLookupFlags: 1016088
- m_FirstAdjustmentRecord:
m_GlyphIndex: 25
m_GlyphValueRecord:
m_XPlacement: 0
m_YPlacement: 0
m_XAdvance: -0.45000002
m_YAdvance: 0
m_SecondAdjustmentRecord:
m_GlyphIndex: 15
m_GlyphValueRecord:
m_XPlacement: 0
m_YPlacement: 0
m_XAdvance: 0
m_YAdvance: 0
m_FeatureLookupFlags: 1016088
- m_FirstAdjustmentRecord:
m_GlyphIndex: 25
m_GlyphValueRecord:
m_XPlacement: 0
m_YPlacement: 0
m_XAdvance: -0.45000002
m_YAdvance: 0
m_SecondAdjustmentRecord:
m_GlyphIndex: 16
m_GlyphValueRecord:
m_XPlacement: 0
m_YPlacement: 0
m_XAdvance: 0
m_YAdvance: 0
m_FeatureLookupFlags: 1016088
- m_FirstAdjustmentRecord:
m_GlyphIndex: 25
m_GlyphValueRecord:
m_XPlacement: 0
m_YPlacement: 0
m_XAdvance: -0.45000002
m_YAdvance: 0
m_SecondAdjustmentRecord:
m_GlyphIndex: 17
m_GlyphValueRecord:
m_XPlacement: 0
m_YPlacement: 0
m_XAdvance: 0
m_YAdvance: 0
m_FeatureLookupFlags: 1016088
- m_FirstAdjustmentRecord:
m_GlyphIndex: 25
m_GlyphValueRecord:
m_XPlacement: 0
m_YPlacement: 0
m_XAdvance: -0.45000002
m_YAdvance: 0
m_SecondAdjustmentRecord:
m_GlyphIndex: 18
m_GlyphValueRecord:
m_XPlacement: 0
m_YPlacement: 0
m_XAdvance: 0
m_YAdvance: 0
m_FeatureLookupFlags: 1016088
- m_FirstAdjustmentRecord:
m_GlyphIndex: 25
m_GlyphValueRecord:
m_XPlacement: 0
m_YPlacement: 0
m_XAdvance: -0.45000002
m_YAdvance: 0
m_SecondAdjustmentRecord:
m_GlyphIndex: 20
m_GlyphValueRecord:
m_XPlacement: 0
m_YPlacement: 0
m_XAdvance: 0
m_YAdvance: 0
m_FeatureLookupFlags: 1016088
- m_FirstAdjustmentRecord:
m_GlyphIndex: 25
m_GlyphValueRecord:
m_XPlacement: 0
m_YPlacement: 0
m_XAdvance: -0.45000002
m_YAdvance: 0
m_SecondAdjustmentRecord:
m_GlyphIndex: 22
m_GlyphValueRecord:
m_XPlacement: 0
m_YPlacement: 0
m_XAdvance: 0
m_YAdvance: 0
m_FeatureLookupFlags: 1016088
- m_FirstAdjustmentRecord:
m_GlyphIndex: 25
m_GlyphValueRecord:
m_XPlacement: 0
m_YPlacement: 0
m_XAdvance: -1.26
m_YAdvance: 0
m_SecondAdjustmentRecord:
m_GlyphIndex: 23
m_GlyphValueRecord:
m_XPlacement: 0
m_YPlacement: 0
m_XAdvance: 0
m_YAdvance: 0
m_FeatureLookupFlags: 1016088
- m_FirstAdjustmentRecord:
m_GlyphIndex: 25
m_GlyphValueRecord:
m_XPlacement: 0
m_YPlacement: 0
m_XAdvance: -0.99
m_YAdvance: 0
m_SecondAdjustmentRecord:
m_GlyphIndex: 30
m_GlyphValueRecord:
m_XPlacement: 0
m_YPlacement: 0
m_XAdvance: 0
m_YAdvance: 0
m_FeatureLookupFlags: 1016088
- m_FirstAdjustmentRecord:
m_GlyphIndex: 25
m_GlyphValueRecord:
m_XPlacement: 0
m_YPlacement: 0
m_XAdvance: -2.97
m_YAdvance: 0
m_SecondAdjustmentRecord:
m_GlyphIndex: 31
m_GlyphValueRecord:
m_XPlacement: 0
m_YPlacement: 0
m_XAdvance: 0
m_YAdvance: 0
m_FeatureLookupFlags: 1016088
- m_FirstAdjustmentRecord:
m_GlyphIndex: 25
m_GlyphValueRecord:
m_XPlacement: 0
m_YPlacement: 0
m_XAdvance: -0.45000002
m_YAdvance: 0
m_SecondAdjustmentRecord:
m_GlyphIndex: 32
m_GlyphValueRecord:
m_XPlacement: 0
m_YPlacement: 0
m_XAdvance: 0
m_YAdvance: 0
m_FeatureLookupFlags: 1016088
- m_FirstAdjustmentRecord:
m_GlyphIndex: 25
m_GlyphValueRecord:
m_XPlacement: 0
m_YPlacement: 0
m_XAdvance: -0.45000002
m_YAdvance: 0
m_SecondAdjustmentRecord:
m_GlyphIndex: 34
m_GlyphValueRecord:
m_XPlacement: 0
m_YPlacement: 0
m_XAdvance: 0
m_YAdvance: 0
m_FeatureLookupFlags: 1016088
- m_FirstAdjustmentRecord:
m_GlyphIndex: 25
m_GlyphValueRecord:
m_XPlacement: 0
m_YPlacement: 0
m_XAdvance: -0.45000002
m_YAdvance: 0
m_SecondAdjustmentRecord:
m_GlyphIndex: 35
m_GlyphValueRecord:
m_XPlacement: 0
m_YPlacement: 0
m_XAdvance: 0
m_YAdvance: 0
m_FeatureLookupFlags: 1016088
- m_FirstAdjustmentRecord:
m_GlyphIndex: 25
m_GlyphValueRecord:
m_XPlacement: 0
m_YPlacement: 0
m_XAdvance: -0.45000002
m_YAdvance: 0
m_SecondAdjustmentRecord:
m_GlyphIndex: 36
m_GlyphValueRecord:
m_XPlacement: 0
m_YPlacement: 0
m_XAdvance: 0
m_YAdvance: 0
m_FeatureLookupFlags: 1016088
- m_FirstAdjustmentRecord:
m_GlyphIndex: 25
m_GlyphValueRecord:
m_XPlacement: 0
m_YPlacement: 0
m_XAdvance: -0.45000002
m_YAdvance: 0
m_SecondAdjustmentRecord:
m_GlyphIndex: 38
m_GlyphValueRecord:
m_XPlacement: 0
m_YPlacement: 0
m_XAdvance: 0
m_YAdvance: 0
m_FeatureLookupFlags: 1016088
- m_FirstAdjustmentRecord:
m_GlyphIndex: 25
m_GlyphValueRecord:
m_XPlacement: 0
m_YPlacement: 0
m_XAdvance: -0.45000002
m_YAdvance: 0
m_SecondAdjustmentRecord:
m_GlyphIndex: 39
m_GlyphValueRecord:
m_XPlacement: 0
m_YPlacement: 0
m_XAdvance: 0
m_YAdvance: 0
m_FeatureLookupFlags: 1016088
- m_FirstAdjustmentRecord:
m_GlyphIndex: 25
m_GlyphValueRecord:
m_XPlacement: 0
m_YPlacement: 0
m_XAdvance: -0.45000002
m_YAdvance: 0
m_SecondAdjustmentRecord:
m_GlyphIndex: 41
m_GlyphValueRecord:
m_XPlacement: 0
m_YPlacement: 0
m_XAdvance: 0
m_YAdvance: 0
m_FeatureLookupFlags: 1016088
- m_FirstAdjustmentRecord:
m_GlyphIndex: 25
m_GlyphValueRecord:
m_XPlacement: 0
m_YPlacement: 0
m_XAdvance: -0.45000002
m_YAdvance: 0
m_SecondAdjustmentRecord:
m_GlyphIndex: 42
m_GlyphValueRecord:
m_XPlacement: 0
m_YPlacement: 0
m_XAdvance: 0
m_YAdvance: 0
m_FeatureLookupFlags: 1016088
- m_FirstAdjustmentRecord:
m_GlyphIndex: 25
m_GlyphValueRecord:
m_XPlacement: 0
m_YPlacement: 0
m_XAdvance: -0.45000002
m_YAdvance: 0
m_SecondAdjustmentRecord:
m_GlyphIndex: 43
m_GlyphValueRecord:
m_XPlacement: 0
m_YPlacement: 0
m_XAdvance: 0
m_YAdvance: 0
m_FeatureLookupFlags: 1016088
- m_FirstAdjustmentRecord:
m_GlyphIndex: 25
m_GlyphValueRecord:
m_XPlacement: 0
m_YPlacement: 0
m_XAdvance: -0.45000002
m_YAdvance: 0
m_SecondAdjustmentRecord:
m_GlyphIndex: 44
m_GlyphValueRecord:
m_XPlacement: 0
m_YPlacement: 0
m_XAdvance: 0
m_YAdvance: 0
m_FeatureLookupFlags: 1016088
- m_FirstAdjustmentRecord:
m_GlyphIndex: 25
m_GlyphValueRecord:
m_XPlacement: 0
m_YPlacement: 0
m_XAdvance: -0.45000002
m_YAdvance: 0
m_SecondAdjustmentRecord:
m_GlyphIndex: 46
m_GlyphValueRecord:
m_XPlacement: 0
m_YPlacement: 0
m_XAdvance: 0
m_YAdvance: 0
m_FeatureLookupFlags: 1016088
- m_FirstAdjustmentRecord:
m_GlyphIndex: 25
m_GlyphValueRecord:
m_XPlacement: 0
m_YPlacement: 0
m_XAdvance: -0.45000002
m_YAdvance: 0
m_SecondAdjustmentRecord:
m_GlyphIndex: 48
m_GlyphValueRecord:
m_XPlacement: 0
m_YPlacement: 0
m_XAdvance: 0
m_YAdvance: 0
m_FeatureLookupFlags: 1016088
- m_FirstAdjustmentRecord:
m_GlyphIndex: 25
m_GlyphValueRecord:
m_XPlacement: 0
m_YPlacement: 0
m_XAdvance: -1.26
m_YAdvance: 0
m_SecondAdjustmentRecord:
m_GlyphIndex: 49
m_GlyphValueRecord:
m_XPlacement: 0
m_YPlacement: 0
m_XAdvance: 0
m_YAdvance: 0
m_FeatureLookupFlags: 1016088
- m_FirstAdjustmentRecord:
m_GlyphIndex: 25
m_GlyphValueRecord:
m_XPlacement: 0
m_YPlacement: 0
m_XAdvance: -0.99
m_YAdvance: 0
m_SecondAdjustmentRecord:
m_GlyphIndex: 56
m_GlyphValueRecord:
m_XPlacement: 0
m_YPlacement: 0
m_XAdvance: 0
m_YAdvance: 0
m_FeatureLookupFlags: 1016088
- m_FirstAdjustmentRecord: - m_FirstAdjustmentRecord:
m_GlyphIndex: 26 m_GlyphIndex: 26
m_GlyphValueRecord: m_GlyphValueRecord:
File diff suppressed because one or more lines are too long
+148 -24
View File
@@ -1,25 +1,149 @@
Logger initiated at 5/16/2026 11:47:02 PM Logger initiated at 7/29/2026 1:21:58 PM
[5/16/2026 11:47:02 PM] Cupid settings updated [7/29/2026 1:21:58 PM] Cupid settings updated
[5/16/2026 11:47:02 PM] Cupid settings updated [7/29/2026 1:21:58 PM] Cupid settings updated
[5/16/2026 11:47:10 PM] Starting matchmake as warlock [7/29/2026 1:22:00 PM] Starting matchmake as warlock
[5/16/2026 11:47:13 PM] Got into a room [7/29/2026 1:22:02 PM] Got into a room
[5/16/2026 11:47:13 PM] {"ok":true,"entry_fee":21,"rc_prize":34,"for_red":{"Players":[{"Name":"warlock2","LastSeen":1778955432808,"UserId":3,"l10_wins":1,"l10_losses":3},{"Name":"warlock","LastSeen":1778955433214,"UserId":2,"l10_wins":3,"l10_losses":1}],"GameName":"soccar","Port":26614,"InitTime":1778955432808,"entry_fee":21,"match_id":32,"instance_started":true,"rc_prize":34,"your_team":"red"},"for_blue":{"Players":[{"Name":"warlock2","LastSeen":1778955432808,"UserId":3,"l10_wins":1,"l10_losses":3},{"Name":"warlock","LastSeen":1778955433214,"UserId":2,"l10_wins":3,"l10_losses":1}],"GameName":"soccar","Port":26614,"InitTime":1778955432808,"entry_fee":21,"match_id":32,"instance_started":true,"rc_prize":34,"your_team":"blue"}} [7/29/2026 1:22:02 PM] {"ok":true,"entry_fee":21,"rc_prize":34,"for_red":{"Players":[{"Name":"choel","LastSeen":1785311520437,"UserId":9,"l10_wins":7,"l10_losses":0},{"Name":"warlock","LastSeen":1785311520886,"UserId":2,"l10_wins":8,"l10_losses":2}],"GameName":"soccar","Port":26815,"InitTime":1785311520437,"entry_fee":21,"match_id":535,"instance_started":true,"rc_prize":34,"your_team":"red"},"for_blue":{"Players":[{"Name":"choel","LastSeen":1785311520437,"UserId":9,"l10_wins":7,"l10_losses":0},{"Name":"warlock","LastSeen":1785311520886,"UserId":2,"l10_wins":8,"l10_losses":2}],"GameName":"soccar","Port":26815,"InitTime":1785311520437,"entry_fee":21,"match_id":535,"instance_started":true,"rc_prize":34,"your_team":"blue"}}
[5/16/2026 11:47:13 PM] Configured dedicated match reporting for match id 32 with secret 38516e39d3406225b7c3015a66e5d25c54e9b2024c0755212122bdcea3e3a328 and internal api base https://kickkingsapi.playpoolstudios.com [7/29/2026 1:22:02 PM] Configured dedicated match reporting for match id 535 with secret 38516e39d3406225b7c3015a66e5d25c54e9b2024c0755212122bdcea3e3a328 and internal api base https://kkapi.playpoolstudios.com
[5/16/2026 11:47:13 PM] Setting cupid to load game scene [7/29/2026 1:22:02 PM] Setting cupid to load game scene
[5/16/2026 11:47:13 PM] Loading game scene [7/29/2026 1:22:02 PM] Loading game scene
[5/16/2026 11:47:17 PM] Starting client at $kickkingsapi.playpoolstudios.com:26614 [7/29/2026 1:22:07 PM] Starting client at $kkapi.playpoolstudios.com:26815
[5/16/2026 11:47:18 PM] Client connected [7/29/2026 1:22:07 PM] Client connected
[5/16/2026 11:47:26 PM] Selected team changed from Red to Blue [7/29/2026 1:22:14 PM] Selected team changed from Red to Blue
[5/16/2026 11:47:30 PM] Score changed from 0 to 1 [7/29/2026 1:22:19 PM] Selected team changed from Blue to Red
[5/16/2026 11:47:33 PM] Selected team changed from Blue to Red [7/29/2026 1:22:26 PM] Selected team changed from Red to Blue
[5/16/2026 11:47:39 PM] Selected team changed from Red to Blue [7/29/2026 1:22:30 PM] Selected team changed from Blue to Red
[5/16/2026 11:47:43 PM] Selected team changed from Blue to Red [7/29/2026 1:22:34 PM] Selected team changed from Red to Blue
[5/16/2026 11:47:48 PM] Selected team changed from Red to Blue [7/29/2026 1:22:37 PM] Selected team changed from Blue to Red
[5/16/2026 11:47:50 PM] Score changed from 1 to 2 [7/29/2026 1:22:44 PM] Selected team changed from Red to Blue
[5/16/2026 11:47:53 PM] Selected team changed from Blue to Red [7/29/2026 1:22:48 PM] Selected team changed from Blue to Red
[5/16/2026 11:47:57 PM] Selected team changed from Red to Blue [7/29/2026 1:22:53 PM] Selected team changed from Red to Blue
[5/16/2026 11:48:02 PM] Score changed from 2 to 3 [7/29/2026 1:22:57 PM] Selected team changed from Blue to Red
[5/16/2026 11:48:14 PM] Client disconnected [7/29/2026 1:23:01 PM] Score changed from 0 to 1
[5/16/2026 11:48:18 PM] Cupid settings updated [7/29/2026 1:23:04 PM] Selected team changed from Red to Blue
[5/16/2026 11:48:18 PM] Cupid settings updated [7/29/2026 1:23:11 PM] Selected team changed from Blue to Red
[7/29/2026 1:23:19 PM] Selected team changed from Red to Blue
[7/29/2026 1:23:24 PM] Selected team changed from Blue to Red
[7/29/2026 1:23:30 PM] Selected team changed from Red to Blue
[7/29/2026 1:23:35 PM] Selected team changed from Blue to Red
[7/29/2026 1:23:42 PM] Selected team changed from Red to Blue
[7/29/2026 1:23:46 PM] Selected team changed from Blue to Red
[7/29/2026 1:23:55 PM] Selected team changed from Red to Blue
[7/29/2026 1:23:59 PM] Selected team changed from Blue to Red
[7/29/2026 1:24:07 PM] Selected team changed from Red to Blue
[7/29/2026 1:24:10 PM] Selected team changed from Blue to Red
[7/29/2026 1:24:19 PM] Selected team changed from Red to Blue
[7/29/2026 1:24:24 PM] Selected team changed from Blue to Red
[7/29/2026 1:24:30 PM] Selected team changed from Red to Blue
[7/29/2026 1:24:36 PM] Selected team changed from Blue to Red
[7/29/2026 1:24:44 PM] Score changed from 1 to 2
[7/29/2026 1:24:48 PM] Selected team changed from Red to Blue
[7/29/2026 1:24:52 PM] Selected team changed from Blue to Red
[7/29/2026 1:24:58 PM] Selected team changed from Red to Blue
[7/29/2026 1:25:04 PM] Score changed from 0 to 1
[7/29/2026 1:25:07 PM] Selected team changed from Blue to Red
[7/29/2026 1:25:16 PM] Selected team changed from Red to Blue
[7/29/2026 1:25:18 PM] Score changed from 1 to 2
[7/29/2026 1:25:21 PM] Selected team changed from Blue to Red
[7/29/2026 1:25:27 PM] Selected team changed from Red to Blue
[7/29/2026 1:25:34 PM] Selected team changed from Blue to Red
[7/29/2026 1:25:40 PM] Selected team changed from Red to Blue
[7/29/2026 1:25:45 PM] Selected team changed from Blue to Red
[7/29/2026 1:25:56 PM] Selected team changed from Red to Blue
[7/29/2026 1:26:00 PM] Score changed from 2 to 3
[7/29/2026 1:26:11 PM] Configured dedicated match reporting for match id 536 with secret 38516e39d3406225b7c3015a66e5d25c54e9b2024c0755212122bdcea3e3a328 and internal api base https://kkapi.playpoolstudios.com
[7/29/2026 1:26:11 PM] Client disconnected
[7/29/2026 1:26:15 PM] Starting client at $kkapi.playpoolstudios.com:26172
[7/29/2026 1:26:15 PM] Client connected
[7/29/2026 1:26:20 PM] Selected team changed from Red to Blue
[7/29/2026 1:26:25 PM] Selected team changed from Blue to Red
[7/29/2026 1:26:33 PM] Selected team changed from Red to Blue
[7/29/2026 1:26:37 PM] Selected team changed from Blue to Red
[7/29/2026 1:26:48 PM] Selected team changed from Red to Blue
[7/29/2026 1:26:56 PM] Selected team changed from Blue to Red
[7/29/2026 1:27:03 PM] Selected team changed from Red to Blue
[7/29/2026 1:27:09 PM] Selected team changed from Blue to Red
[7/29/2026 1:27:14 PM] Selected team changed from Red to Blue
[7/29/2026 1:27:24 PM] Selected team changed from Blue to Red
[7/29/2026 1:27:32 PM] Selected team changed from Red to Blue
[7/29/2026 1:27:37 PM] Selected team changed from Blue to Red
[7/29/2026 1:27:45 PM] Selected team changed from Red to Blue
[7/29/2026 1:27:49 PM] Selected team changed from Blue to Red
[7/29/2026 1:27:55 PM] Score changed from 0 to 1
[7/29/2026 1:27:58 PM] Selected team changed from Red to Blue
[7/29/2026 1:28:02 PM] Selected team changed from Blue to Red
[7/29/2026 1:28:08 PM] Selected team changed from Red to Blue
[7/29/2026 1:28:15 PM] Selected team changed from Blue to Red
[7/29/2026 1:28:23 PM] Selected team changed from Red to Blue
[7/29/2026 1:28:28 PM] Selected team changed from Blue to Red
[7/29/2026 1:28:35 PM] Selected team changed from Red to Blue
[7/29/2026 1:28:39 PM] Selected team changed from Blue to Red
[7/29/2026 1:28:52 PM] Selected team changed from Red to Blue
[7/29/2026 1:28:55 PM] Score changed from 0 to 1
[7/29/2026 1:28:58 PM] Selected team changed from Blue to Red
[7/29/2026 1:29:06 PM] Selected team changed from Red to Blue
[7/29/2026 1:29:14 PM] Selected team changed from Blue to Red
[7/29/2026 1:29:18 PM] Selected team changed from Red to Blue
[7/29/2026 1:29:23 PM] Selected team changed from Blue to Red
[7/29/2026 1:29:32 PM] Selected team changed from Red to Blue
[7/29/2026 1:29:36 PM] Selected team changed from Blue to Red
[7/29/2026 1:29:42 PM] Selected team changed from Red to Blue
[7/29/2026 1:29:46 PM] Selected team changed from Blue to Red
[7/29/2026 1:29:52 PM] Selected team changed from Red to Blue
[7/29/2026 1:29:56 PM] Selected team changed from Blue to Red
[7/29/2026 1:30:11 PM] Selected team changed from Red to Blue
[7/29/2026 1:30:16 PM] Selected team changed from Blue to Red
[7/29/2026 1:30:21 PM] Selected team changed from Red to Blue
[7/29/2026 1:30:27 PM] Selected team changed from Blue to Red
[7/29/2026 1:30:30 PM] Score changed from 1 to 2
[7/29/2026 1:30:33 PM] Selected team changed from Red to Blue
[7/29/2026 1:30:40 PM] Selected team changed from Blue to Red
[7/29/2026 1:30:45 PM] Selected team changed from Red to Blue
[7/29/2026 1:30:50 PM] Selected team changed from Blue to Red
[7/29/2026 1:30:55 PM] Selected team changed from Red to Blue
[7/29/2026 1:31:01 PM] Selected team changed from Blue to Red
[7/29/2026 1:31:03 PM] Score changed from 2 to 3
[7/29/2026 1:31:24 PM] Configured dedicated match reporting for match id 537 with secret 38516e39d3406225b7c3015a66e5d25c54e9b2024c0755212122bdcea3e3a328 and internal api base https://kkapi.playpoolstudios.com
[7/29/2026 1:31:24 PM] Client disconnected
[7/29/2026 1:31:28 PM] Starting client at $kkapi.playpoolstudios.com:26149
[7/29/2026 1:31:28 PM] Client connected
[7/29/2026 1:31:33 PM] Selected team changed from Red to Blue
[7/29/2026 1:31:37 PM] Selected team changed from Blue to Red
[7/29/2026 1:31:41 PM] Selected team changed from Red to Blue
[7/29/2026 1:31:45 PM] Selected team changed from Blue to Red
[7/29/2026 1:31:50 PM] Selected team changed from Red to Blue
[7/29/2026 1:31:54 PM] Selected team changed from Blue to Red
[7/29/2026 1:32:05 PM] Selected team changed from Red to Blue
[7/29/2026 1:32:12 PM] Selected team changed from Blue to Red
[7/29/2026 1:32:18 PM] Selected team changed from Red to Blue
[7/29/2026 1:32:25 PM] Selected team changed from Blue to Red
[7/29/2026 1:32:32 PM] Selected team changed from Red to Blue
[7/29/2026 1:32:38 PM] Selected team changed from Blue to Red
[7/29/2026 1:32:44 PM] Selected team changed from Red to Blue
[7/29/2026 1:32:56 PM] Selected team changed from Blue to Red
[7/29/2026 1:33:04 PM] Score changed from 0 to 1
[7/29/2026 1:33:07 PM] Selected team changed from Red to Blue
[7/29/2026 1:33:16 PM] Selected team changed from Blue to Red
[7/29/2026 1:33:22 PM] Selected team changed from Red to Blue
[7/29/2026 1:33:31 PM] Selected team changed from Blue to Red
[7/29/2026 1:33:40 PM] Selected team changed from Red to Blue
[7/29/2026 1:33:43 PM] Score changed from 0 to 1
[7/29/2026 1:33:46 PM] Selected team changed from Blue to Red
[7/29/2026 1:33:52 PM] Selected team changed from Red to Blue
[7/29/2026 1:33:58 PM] Selected team changed from Blue to Red
[7/29/2026 1:34:04 PM] Selected team changed from Red to Blue
[7/29/2026 1:34:11 PM] Selected team changed from Blue to Red
[7/29/2026 1:34:16 PM] Selected team changed from Red to Blue
[7/29/2026 1:34:22 PM] Selected team changed from Blue to Red
[7/29/2026 1:34:30 PM] Selected team changed from Red to Blue
[7/29/2026 1:34:34 PM] Selected team changed from Blue to Red
[7/29/2026 1:34:39 PM] Score changed from 1 to 2
[7/29/2026 1:34:42 PM] Selected team changed from Red to Blue
[7/29/2026 1:34:47 PM] Selected team changed from Blue to Red
[7/29/2026 1:34:54 PM] Selected team changed from Red to Blue
[7/29/2026 1:34:58 PM] Selected team changed from Blue to Red
[7/29/2026 1:35:12 PM] Score changed from 2 to 3
[7/29/2026 1:35:21 PM] Client disconnected
[7/29/2026 1:35:23 PM] Cupid settings updated
[7/29/2026 1:35:23 PM] Cupid settings updated
File diff suppressed because one or more lines are too long
+7
View File
@@ -0,0 +1,7 @@
fileFormatVersion: 2
guid: d5d4b6e75e17172409ca64a1f41951a1
TextScriptImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:
+5
View File
@@ -411,3 +411,8 @@
[5/1/2026 1:13:06 AM] Active player connections: 0 [5/1/2026 1:13:06 AM] Active player connections: 0
[5/1/2026 1:13:12 AM] Server will be closed due to no players in, 40 [5/1/2026 1:13:12 AM] Server will be closed due to no players in, 40
[5/1/2026 1:13:22 AM] Server will be closed due to no players in, 30 [5/1/2026 1:13:22 AM] Server will be closed due to no players in, 30
[7/19/2026 12:42:42 AM] Starting server at port 7777
[7/19/2026 12:42:42 AM] Mirror server exception logging enabled
[7/19/2026 12:42:42 AM] Failed to fetch red and blue names, isServer?
[7/19/2026 12:42:42 AM] Starting auto close watchdog
[7/19/2026 12:42:42 AM] Active player connections: 0
+4720 -18
View File
File diff suppressed because it is too large Load Diff
+3070 -3
View File
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
+2
View File
@@ -0,0 +1,2 @@
fileFormatVersion: 2
guid: c886581a7bac8f34ba8f7995eb48db02
+4
View File
@@ -96,10 +96,14 @@ public class Ball : NetworkBehaviour
if(collision.collider.CompareTag("wall")){ if(collision.collider.CompareTag("wall")){
AudioManager.instance.PlayWallHit(vol); AudioManager.instance.PlayWallHit(vol);
if (isServer)
ReplayRecorder.RecordHit("ball_wall", vol, this);
RpcWallHitAudio(vol); RpcWallHitAudio(vol);
} }
else if(collision.collider.CompareTag("Puck")){ else if(collision.collider.CompareTag("Puck")){
AudioManager.instance.PlayBallHit(vol); AudioManager.instance.PlayBallHit(vol);
if (isServer)
ReplayRecorder.RecordHit("ball_puck", vol, this);
RpcBallHitAudio(vol); RpcBallHitAudio(vol);
} }
+1 -5
View File
@@ -169,11 +169,7 @@ public class GameCanvas : MonoBehaviour
CupidLobby.instance.Cancel(); CupidLobby.instance.Cancel();
LoginManager.ClearMatchYourTeam(); LoginManager.ClearMatchYourTeam();
if (NetworkManager.singleton != null && NetworkClient.active) NetManager.StopNetworkingForSceneChange();
{
NetManager.MarkIntentionalClientDisconnect();
NetworkManager.singleton.StopClient();
}
LevelLoadManager.LoadLevel("MainMenu"); LevelLoadManager.LoadLevel("MainMenu");
} }
+75 -7
View File
@@ -161,6 +161,7 @@ public class GameManager : NetworkBehaviour
bool _dedicatedReportedRedJoin; bool _dedicatedReportedRedJoin;
bool _dedicatedReportedBlueJoin; bool _dedicatedReportedBlueJoin;
bool _dedicatedReportedGameOver; bool _dedicatedReportedGameOver;
bool _replayRecordingStarted;
public static Action<Team> OnTeamChanged; public static Action<Team> OnTeamChanged;
public static bool isMoving{ public static bool isMoving{
@@ -489,7 +490,7 @@ public class GameManager : NetworkBehaviour
SwitchTeams(); SwitchTeams();
} }
void SwitchTeams(){ public void SwitchTeams(){
if(!isServer){ if(!isServer){
Debug.LogWarning("SwitchTeams called on client, skipping"); Debug.LogWarning("SwitchTeams called on client, skipping");
return; return;
@@ -555,7 +556,11 @@ public class GameManager : NetworkBehaviour
HandleTurnTimer(); HandleTurnTimer();
if(!gameStarted){ if(!gameStarted){
if(GameTutorialManager.tutorialModeEnabled){
gameStarted = true;
GameCanvas.instance.HideWaitingForOpponentPanel();
Logger.Log("Game started On localhost, tutorial mode enabled");
}
NetPlayer[] players = FindObjectsOfType<NetPlayer>(); NetPlayer[] players = FindObjectsOfType<NetPlayer>();
#if UNITY_EDITOR #if UNITY_EDITOR
if(Input.GetKeyDown(KeyCode.Space)){ if(Input.GetKeyDown(KeyCode.Space)){
@@ -571,6 +576,14 @@ public class GameManager : NetworkBehaviour
Logger.Log("Game started On Server"); Logger.Log("Game started On Server");
} }
} }
// Host practice (tutorial) and dedicated matches both record once NetworkServer is ready.
// Retry until StartRecording succeeds — StartHost can lag one frame behind gameStarted.
if (gameStarted && !_replayRecordingStarted && NetworkServer.active)
{
if (ReplayRecorder.StartRecording(DedicatedMatchId, this))
_replayRecordingStarted = true;
}
} }
UpdateLocalTurnTimerBeep(); UpdateLocalTurnTimerBeep();
@@ -604,7 +617,28 @@ public class GameManager : NetworkBehaviour
} }
} }
bool turnTimerPaused;
public void SetTurnTimerPaused(bool paused)
{
if (!isServer)
{
CmdSetTurnTimerPaused(paused);
return;
}
turnTimerPaused = paused;
}
[Command(requiresAuthority = false)]
void CmdSetTurnTimerPaused(bool paused)
{
turnTimerPaused = paused;
}
void HandleTurnTimer(){ void HandleTurnTimer(){
if (turnTimerPaused)
return;
if(turnTimerCounter < turnTimer){ if(turnTimerCounter < turnTimer){
if(!isMoving && !switchingTeams && gameStarted){ if(!isMoving && !switchingTeams && gameStarted){
turnTimerCounter += Time.deltaTime; turnTimerCounter += Time.deltaTime;
@@ -711,6 +745,7 @@ public class GameManager : NetworkBehaviour
if(hitCounter == 1){ if(hitCounter == 1){
//kickoff goal //kickoff goal
Logger.Log("Kickoff goal"); Logger.Log("Kickoff goal");
ReplayRecorder.RecordGoal(concedingTeam, redScore, blueScore, kickoff: true);
SetKickoffTeam(concedingTeam); SetKickoffTeam(concedingTeam);
StartCoroutine(CoroutineOnGoal(team,true));//true = Kickoff goal, reset only the ball StartCoroutine(CoroutineOnGoal(team,true));//true = Kickoff goal, reset only the ball
hitCounter = 0; hitCounter = 0;
@@ -729,16 +764,19 @@ public class GameManager : NetworkBehaviour
Logger.Log($"Red goal scored, red score is now {redScore}"); Logger.Log($"Red goal scored, red score is now {redScore}");
} }
ReplayRecorder.RecordGoal(concedingTeam, redScore, blueScore, kickoff: false);
SetKickoffTeam(concedingTeam); SetKickoffTeam(concedingTeam);
if(blueScore >= 3){ if(blueScore >= 3){
isGameEnded = true; isGameEnded = true;
ReplayRecorder.StopAndFlush();
ReportDedicatedMatchGameOver(Team.Blue); ReportDedicatedMatchGameOver(Team.Blue);
RpcGameOver(Team.Blue); RpcGameOver(Team.Blue);
gameOver(Team.Blue); gameOver(Team.Blue);
}else if(redScore >= 3){ }else if(redScore >= 3){
isGameEnded = true; isGameEnded = true;
ReplayRecorder.StopAndFlush();
ReportDedicatedMatchGameOver(Team.Red); ReportDedicatedMatchGameOver(Team.Red);
RpcGameOver(Team.Red); RpcGameOver(Team.Red);
gameOver(Team.Red); gameOver(Team.Red);
@@ -808,16 +846,45 @@ public class GameManager : NetworkBehaviour
// LevelLoadManager.LoadLevel("MainMenu"); // LevelLoadManager.LoadLevel("MainMenu");
} }
public void Leave(){ bool _thirdPlayerLeaveTriggered;
NetManager.MarkIntentionalClientDisconnect();
StopClient(); /// <summary>
LevelLoadManager.LoadLevel("MainMenu"); /// Called when the local client spawns into a match. If three <see cref="NetPlayer"/> instances exist
/// (matchmaker sent an extra client into a full room), disconnect and return to the main menu.
/// </summary>
public void OnLocalPlayerJoinedMatch()
{
if (!isClient || _thirdPlayerLeaveTriggered)
return;
StartCoroutine(CoLeaveIfThirdPlayer());
} }
public void Leave(){
LevelLoadManager.instance.Leave();
}
IEnumerator CoLeaveIfThirdPlayer()
{
const int maxFrames = 30;
for (int i = 0; i < maxFrames; i++)
{
yield return null;
if (FindObjectsByType<NetPlayer>(FindObjectsSortMode.None).Length >= 3)
{
_thirdPlayerLeaveTriggered = true;
Logger.Log("Third player in a 2-player match (matchmaker bug); leaving to main menu.");
if (LevelLoadManager.instance != null)
LevelLoadManager.instance.Leave();
else
LevelLoadManager.LoadLevel("MainMenu");
yield break;
}
}
}
public void StopClient(){ public void StopClient(){
try{ try{
NetworkManager.singleton.StopClient(); NetManager.StopNetworkingForSceneChange();
}catch(Exception e){ }catch(Exception e){
Logger.Log("Error stopping client: " + e.Message); Logger.Log("Error stopping client: " + e.Message);
} }
@@ -909,6 +976,7 @@ public class GameManager : NetworkBehaviour
} }
IEnumerator CoroutineReset(bool kickoff = false){ IEnumerator CoroutineReset(bool kickoff = false){
ReplayRecorder.RecordReset(kickoff);
float resetDuration = 0.5f; float resetDuration = 0.5f;
if(!kickoff){ if(!kickoff){
foreach(Puck puck in pucks){ foreach(Puck puck in pucks){
+233 -19
View File
@@ -42,6 +42,25 @@ public class GameOverCanvas : MonoBehaviour
public float returnToMenuCountdown = 15f; public float returnToMenuCountdown = 15f;
/// <summary>Each player needs at least 2.0 RC (20 coin units) to rematch.</summary>
const int MinimumRematchRcCoins = 20;
[Header("Bet Limit")]
public TMP_Text txtRcBalance;
public TMP_Text txtBetLimitWarning;
public CanvasGroup betLimitAdjustPanel;
//minVal: 2, max Val 500, when its 500, show ∞ on the text
public Slider betLimitSlider;
public TMP_Text txtBetLimitSliderValue;
public Button btnBetLimitAdjustAccept;
public Button btnBetLimitAdjustCancel;
const string PersonalBetLimitPrefsKey = "WalkInvest.PersonalBetLimit";
const int BetLimitMin = 2;
const int BetLimitMax = 500;
const int BetLimitUnlimited = 500;
int rematchOpponentBetLimitCoins = BetLimitUnlimited;
[Header("Rematch panel")] [Header("Rematch panel")]
public CanvasGroup rematchPanel; public CanvasGroup rematchPanel;
@@ -83,6 +102,139 @@ public class GameOverCanvas : MonoBehaviour
btnConfirmBet.onClick.AddListener(OnBetAccepted); btnConfirmBet.onClick.AddListener(OnBetAccepted);
btnCancelBet.onClick.AddListener(OnBetCancelled); btnCancelBet.onClick.AddListener(OnBetCancelled);
SetupBetLimitUi();
}
void SetupBetLimitUi()
{
if (betLimitSlider != null)
{
betLimitSlider.minValue = BetLimitMin;
betLimitSlider.maxValue = BetLimitMax;
betLimitSlider.wholeNumbers = true;
betLimitSlider.onValueChanged.AddListener(OnBetLimitSliderValueChanged);
}
if (btnBetLimitAdjustAccept != null)
btnBetLimitAdjustAccept.onClick.AddListener(OnBetLimitAdjustAccepted);
if (btnBetLimitAdjustCancel != null)
btnBetLimitAdjustCancel.onClick.AddListener(CloseBetLimitAdjuster);
var warningButton = txtBetLimitWarning != null
? txtBetLimitWarning.GetComponentInChildren<Button>()
: null;
if (warningButton != null)
warningButton.onClick.AddListener(OpenBetLimitAdjuster);
}
public static int GetPersonalBetLimit()
{
return PlayerPrefs.GetInt(PersonalBetLimitPrefsKey, BetLimitUnlimited);
}
static int EffectiveBetLimitCap(int limitCoins) =>
limitCoins >= BetLimitUnlimited ? int.MaxValue : limitCoins;
int GetRematchMaxBetCoins()
{
int maxBet = Mathf.Min(
EffectiveBetLimitCap(rematchOpponentBetLimitCoins),
GetRcCoins(LevelLoadManager.myPlayer),
GetRcCoins(LevelLoadManager.opponentPlayer));
return Mathf.Max(0, maxBet);
}
void ApplyRematchBetSliderLimits()
{
if (betSlider == null)
return;
int maxBet = GetRematchMaxBetCoins();
betSlider.maxValue = maxBet;
if (maxBet <= 0)
{
betSlider.minValue = 0;
betSlider.value = 0;
}
else
{
betSlider.minValue = Mathf.Clamp(maxBet / 10f, 5, 10000);
betSlider.value = Mathf.Clamp(maxBet / 2, betSlider.minValue, maxBet);
}
OnBetSliderValueChanged(betSlider.value);
}
static void SetPersonalBetLimit(int limitCoins)
{
limitCoins = Mathf.Clamp(limitCoins, BetLimitMin, BetLimitMax);
PlayerPrefs.SetInt(PersonalBetLimitPrefsKey, limitCoins);
PlayerPrefs.Save();
}
static string FormatBetLimitLabel(int limitCoins)
{
if (limitCoins >= BetLimitUnlimited)
return "∞";
return CoinHelper.FormatString(limitCoins) + " RC";
}
static string FormatBetLimitWarningText(int limitCoins) =>
"Max Bet : " + FormatBetLimitLabel(limitCoins);
void UpdateBetLimitWarningText()
{
if (txtBetLimitWarning != null)
txtBetLimitWarning.text = FormatBetLimitWarningText(GetPersonalBetLimit());
}
void OnBetLimitSliderValueChanged(float value)
{
if (txtBetLimitSliderValue != null)
txtBetLimitSliderValue.text = FormatBetLimitLabel(Mathf.RoundToInt(value));
}
void ApplyBetLimitVisibility()
{
bool isLoser = myTeam != winningTeam;
if (txtBetLimitWarning != null)
txtBetLimitWarning.gameObject.SetActive(isLoser);
if (!isLoser)
return;
UpdateBetLimitWarningText();
}
public void OpenBetLimitAdjuster()
{
if (betLimitAdjustPanel == null)
return;
int limit = GetPersonalBetLimit();
if (betLimitSlider != null)
betLimitSlider.SetValueWithoutNotify(limit);
OnBetLimitSliderValueChanged(limit);
betLimitAdjustPanel.DOFade(1, 0.25f);
betLimitAdjustPanel.blocksRaycasts = true;
betLimitAdjustPanel.interactable = true;
}
public void CloseBetLimitAdjuster()
{
if (betLimitAdjustPanel == null)
return;
betLimitAdjustPanel.DOFade(0, 0.25f);
betLimitAdjustPanel.blocksRaycasts = false;
betLimitAdjustPanel.interactable = false;
}
void OnBetLimitAdjustAccepted()
{
if (betLimitSlider != null)
SetPersonalBetLimit(Mathf.RoundToInt(betLimitSlider.value));
UpdateBetLimitWarningText();
CloseBetLimitAdjuster();
} }
void OnBetAccepted(){ void OnBetAccepted(){
@@ -102,14 +254,18 @@ public class GameOverCanvas : MonoBehaviour
} }
void OnBtnRematchClicked(){ void OnBtnRematchClicked(){
// LevelLoadManager.LoadLevel("Game"); if (!BothPlayersHaveMinimumRematchRc())
return;
if (txtBetLimitWarning != null)
txtBetLimitWarning.gameObject.SetActive(false);
NetPlayer.localPlayer.RequestRematch(); NetPlayer.localPlayer.RequestRematch();
SetRematchPendingState(true); SetRematchPendingState(true);
} }
public void OnRematchRequested(){ public void OnRematchRequested(int opponentMaxBetLimitCoins){
rematchOpponentBetLimitCoins = opponentMaxBetLimitCoins;
if(winningTeam == myTeam){ if(winningTeam == myTeam){
//Only i can initiate the rematch, so here we go //Only the loser can initiate the rematch; winner sets the stake
ShowRematchPanel(); ShowRematchPanel();
}else{ }else{
rematchWarningLoser.text = "Waiting for opponent to accept"; rematchWarningLoser.text = "Waiting for opponent to accept";
@@ -129,7 +285,7 @@ public class GameOverCanvas : MonoBehaviour
void OnBtnLeaveGameClicked(){ void OnBtnLeaveGameClicked(){
GameManager.instance.Leave(); LevelLoadManager.instance.Leave();
} }
void CollectOriginalPositionsAndScales(){ void CollectOriginalPositionsAndScales(){
@@ -178,6 +334,13 @@ public class GameOverCanvas : MonoBehaviour
rematchPanel.alpha=0; rematchPanel.alpha=0;
rematchPanel.blocksRaycasts = false; rematchPanel.blocksRaycasts = false;
rematchPanel.interactable = false; rematchPanel.interactable = false;
if (betLimitAdjustPanel != null)
{
betLimitAdjustPanel.alpha = 0;
betLimitAdjustPanel.blocksRaycasts = false;
betLimitAdjustPanel.interactable = false;
}
} }
Team winningTeam; Team winningTeam;
@@ -217,6 +380,8 @@ public class GameOverCanvas : MonoBehaviour
p1_winner.gameObject.SetActive(false); p1_winner.gameObject.SetActive(false);
p2_winner.gameObject.SetActive(true); p2_winner.gameObject.SetActive(true);
} }
ApplyBetLimitVisibility();
} }
float rcPrize = 0; float rcPrize = 0;
@@ -246,16 +411,16 @@ public class GameOverCanvas : MonoBehaviour
item.localScale = new Vector3(0, 0, 0); item.localScale = new Vector3(0, 0, 0);
} }
if(winningTeam == myTeam){ if (GameTutorialManager.tutorialModeEnabled)
rcPrize = 0;
else if (winningTeam == myTeam)
rcPrize = CoinHelper.Format(GameManager.MatchRcPrizeCoins); rcPrize = CoinHelper.Format(GameManager.MatchRcPrizeCoins);
}
btnRematch.interactable = winningTeam != myTeam; if (btnRematch != null)
if(winningTeam == myTeam){ btnRematch.gameObject.SetActive(!GameTutorialManager.tutorialModeEnabled);
rematchWarningLoser.text = "Only the loser can request a rematch";
}else{ UpdateRematchAvailability();
rematchWarningLoser.text = ""; ApplyRcBalancesToUi(null);
}
StartCoroutine(CoroutineShow()); StartCoroutine(CoroutineShow());
@@ -291,10 +456,13 @@ public class GameOverCanvas : MonoBehaviour
yield return new WaitForSeconds(scaleTime * 0.5f); yield return new WaitForSeconds(scaleTime * 0.5f);
//Rewards //Rewards
float ccReward = GameTutorialManager.tutorialModeEnabled ? 0f : 100f;
StartCoroutine(CoroutineSetTextNumber(rcPrize, txtRewardRC, 10, "N1", "+", " RC")); StartCoroutine(CoroutineSetTextNumber(rcPrize, txtRewardRC, 10, "N1", "+", " RC"));
StartCoroutine(CoroutineSetTextNumber(100, txtRewardCC, 100, "N0", "+", " CC")); StartCoroutine(CoroutineSetTextNumber(ccReward, txtRewardCC, 100, "N0", "+", " CC"));
txtBetRC.text = CoinHelper.FormatString(GameManager.MatchRcPrizeCoins) + " RC"; txtBetRC.text = GameTutorialManager.tutorialModeEnabled
? "0 RC"
: CoinHelper.FormatString(GameManager.MatchRcPrizeCoins) + " RC";
yield return new WaitForSeconds(1f); yield return new WaitForSeconds(1f);
@@ -333,17 +501,14 @@ public class GameOverCanvas : MonoBehaviour
} }
GameManager.instance.Leave(); LevelLoadManager.instance.Leave();
} }
public void ShowRematchPanel(){ public void ShowRematchPanel(){
SetRematchPendingState(true); SetRematchPendingState(true);
ApplyRematchBetSliderLimits();
StartCoroutine(CoroutineShowRematchPanel()); StartCoroutine(CoroutineShowRematchPanel());
betSlider.maxValue = (LevelLoadManager.myPlayer.rc < LevelLoadManager.opponentPlayer.rc) ? LevelLoadManager.myPlayer.rc : LevelLoadManager.opponentPlayer.rc;
betSlider.value = betSlider.maxValue / 2;
betSlider.minValue = Mathf.Clamp(betSlider.maxValue /10f,5,10000);
} }
IEnumerator CoroutineShowRematchPanel(){ IEnumerator CoroutineShowRematchPanel(){
@@ -406,6 +571,55 @@ public class GameOverCanvas : MonoBehaviour
txtMyRCBalance.text = myText; txtMyRCBalance.text = myText;
if (txtOpponentRCBalance != null) if (txtOpponentRCBalance != null)
txtOpponentRCBalance.text = oppText; txtOpponentRCBalance.text = oppText;
if (txtRcBalance != null)
txtRcBalance.text = loadingPlaceholder ?? (my != null ? CoinHelper.FormatString((int)my.rc) + " RC" : "0.0 RC");
if (loadingPlaceholder == null)
{
UpdateRematchAvailability();
if (rematchPanel != null && rematchPanel.alpha > 0.01f)
ApplyRematchBetSliderLimits();
}
}
static int GetRcCoins(MatchmadePlayer player) =>
player == null ? 0 : Mathf.Max(0, Mathf.FloorToInt(player.rc));
bool BothPlayersHaveMinimumRematchRc()
{
return GetRcCoins(LevelLoadManager.myPlayer) >= MinimumRematchRcCoins
&& GetRcCoins(LevelLoadManager.opponentPlayer) >= MinimumRematchRcCoins;
}
void UpdateRematchAvailability()
{
if (GameTutorialManager.tutorialModeEnabled)
{
btnRematch.interactable = false;
if (rematchWarningLoser != null)
rematchWarningLoser.text = "";
return;
}
if (winningTeam == myTeam)
{
btnRematch.interactable = false;
if (rematchWarningLoser != null)
rematchWarningLoser.text = "Only the loser can request a rematch";
return;
}
if (!BothPlayersHaveMinimumRematchRc())
{
btnRematch.interactable = false;
if (rematchWarningLoser != null)
rematchWarningLoser.text = "Not enough RC";
return;
}
btnRematch.interactable = true;
if (rematchWarningLoser != null)
rematchWarningLoser.text = "";
} }
IEnumerator FetchPlayerRcAndApply(string baseUrl, MatchmadePlayer player) IEnumerator FetchPlayerRcAndApply(string baseUrl, MatchmadePlayer player)
+309
View File
@@ -0,0 +1,309 @@
using System;
using System.Collections;
using Mirror;
using UnityEngine;
using UnityEngine.Networking;
using UnityEngine.UI;
using DG.Tweening;
public class GameTutorialManager : MonoBehaviour
{
public const string CpuOpponentName = "CPU";
public const string DefaultGameSceneName = "Game";
public static bool tutorialModeTrigger = false;
public bool isTutorial = false;
public static bool tutorialModeEnabled = false;
public AiBotController aiController;
[Header("UI")]
public CanvasGroup intro_shoot;
public CanvasGroup intro_goal;
public float introFadeDuration = 0.3f;
Button _introShootButton;
Button _introGoalButton;
bool _shootIntroDismissed;
bool _goalIntroDismissed;
bool _introVisible;
void Awake()
{
tutorialModeEnabled = false;
if (isTutorial)
tutorialModeTrigger = true;
if (tutorialModeTrigger)
tutorialModeEnabled = true;
tutorialModeTrigger = false;
if (!tutorialModeEnabled)
{
HideIntroImmediate(intro_shoot);
HideIntroImmediate(intro_goal);
}
}
void OnEnable()
{
GameManager.OnTeamChanged += OnTeamChanged;
}
void OnDisable()
{
GameManager.OnTeamChanged -= OnTeamChanged;
}
void OnDestroy()
{
if (tutorialModeEnabled)
tutorialModeEnabled = false;
if (intro_shoot != null)
DOTween.Kill(intro_shoot);
if (intro_goal != null)
DOTween.Kill(intro_goal);
}
void Start()
{
if (tutorialModeEnabled)
{
NetManager.StopNetworkingForSceneChange();
NetworkManager.singleton.networkAddress = "localhost";
NetworkManager.singleton.StartHost();
WireIntroButtons();
HideIntroImmediate(intro_goal);
HideIntroImmediate(intro_shoot);
StartCoroutine(SetupAiWhenReady());
StartCoroutine(ShowShootIntroWhenReady());
}
}
void WireIntroButtons()
{
if (intro_shoot != null)
_introShootButton = intro_shoot.GetComponentInChildren<Button>(true);
if (intro_goal != null)
_introGoalButton = intro_goal.GetComponentInChildren<Button>(true);
if (_introShootButton != null)
_introShootButton.onClick.AddListener(OnShootIntroDismissed);
if (_introGoalButton != null)
_introGoalButton.onClick.AddListener(OnGoalIntroDismissed);
}
IEnumerator ShowShootIntroWhenReady()
{
while (GameManager.instance == null || !GameManager.instance.gameStarted)
yield return null;
while (NetPlayer.localPlayer == null)
yield return null;
ShowIntro(intro_shoot);
}
void OnTeamChanged(Team team)
{
if (!tutorialModeEnabled || _introVisible)
return;
if (team != GetPlayerTeam())
return;
if (!_shootIntroDismissed || _goalIntroDismissed)
return;
ShowIntro(intro_goal);
}
void OnShootIntroDismissed()
{
if (_shootIntroDismissed)
return;
_shootIntroDismissed = true;
DismissIntro(intro_shoot);
}
void OnGoalIntroDismissed()
{
if (_goalIntroDismissed)
return;
_goalIntroDismissed = true;
DismissIntro(intro_goal);
}
void ShowIntro(CanvasGroup group)
{
if (group == null)
return;
EnsureTutorialCanvasVisible(group);
DOTween.Kill(group);
group.gameObject.SetActive(true);
group.alpha = 1f;
group.interactable = true;
group.blocksRaycasts = true;
_introVisible = true;
if (GameManager.instance != null)
GameManager.instance.SetTurnTimerPaused(true);
}
void DismissIntro(CanvasGroup group)
{
if (group == null)
return;
group.interactable = false;
group.blocksRaycasts = false;
DOTween.Kill(group);
group.DOFade(0f, introFadeDuration)
.SetEase(Ease.InOutSine)
.OnComplete(() =>
{
group.gameObject.SetActive(false);
_introVisible = false;
if (GameManager.instance != null)
GameManager.instance.SetTurnTimerPaused(false);
});
}
static void HideIntroImmediate(CanvasGroup group)
{
if (group == null)
return;
DOTween.Kill(group);
group.alpha = 0f;
group.interactable = false;
group.blocksRaycasts = false;
group.gameObject.SetActive(false);
}
static void EnsureTutorialCanvasVisible(CanvasGroup group)
{
Transform root = group.transform.root;
if (root.localScale == Vector3.zero)
root.localScale = Vector3.one;
}
static Team GetPlayerTeam()
{
if (NetPlayer.localPlayer != null)
return NetPlayer.localPlayer.myTeam;
return GameManager.MyTeam;
}
/// <summary>Call from the main menu before loading the game scene.</summary>
public static void PrepareLaunch(MatchmadePlayer myPlayer, MatchmadePlayer cpuPlayer, Team myTeam = Team.Red)
{
LoginManager.ClearMatchYourTeam();
GameManager.MyTeam = myTeam;
GameManager.MatchRcPrizeCoins = 0;
GameManager.ConfigureDedicatedMatchReporting(0);
if (myTeam == Team.Red)
{
GameManager.RedPlayer = myPlayer;
GameManager.BluePlayer = cpuPlayer;
}
else
{
GameManager.RedPlayer = cpuPlayer;
GameManager.BluePlayer = myPlayer;
}
LevelLoadManager.myPlayer = myPlayer;
LevelLoadManager.opponentPlayer = cpuPlayer;
if (LevelLoadManager.instance != null)
LevelLoadManager.instance.SetupMatchMade(myTeam, myPlayer, cpuPlayer, "0 RC");
tutorialModeTrigger = true;
}
public static MatchmadePlayer CreateCpuOpponent()
{
return new MatchmadePlayer
{
Name = CpuOpponentName,
l10_wins = 10,
l10_losses = 0
};
}
public static MatchmadePlayer CreateMyPlayerFromUser(UserData user)
{
return new MatchmadePlayer
{
Name = user.username,
UserId = user.id,
rc = user.rc
};
}
public static IEnumerator CoFetchPlayerL10(MatchmadePlayer player)
{
if (player == null || player.UserId <= 0)
yield break;
string baseUrl = (GameManager.DedicatedInternalApiBase ?? LoginManager.AuthBaseUrl ?? "").TrimEnd('/');
if (string.IsNullOrEmpty(baseUrl))
yield break;
string url = baseUrl + "/players/" + player.UserId + "/l10";
using (var req = UnityWebRequest.Get(url))
{
yield return req.SendWebRequest();
if (req.result != UnityWebRequest.Result.Success)
{
Logger.Log("Tutorial L10 fetch failed: " + req.error + " " + url);
yield break;
}
var resp = JsonUtility.FromJson<PlayerL10Response>(req.downloadHandler.text);
if (resp != null && resp.ok)
{
player.l10_wins = resp.l10_wins;
player.l10_losses = resp.l10_losses;
}
}
}
[Serializable]
class PlayerL10Response
{
public bool ok;
public int player_id;
public int l10_wins;
public int l10_losses;
}
IEnumerator SetupAiWhenReady()
{
float timeout = 5f;
while (NetPlayer.localPlayer == null && timeout > 0f)
{
timeout -= Time.deltaTime;
yield return null;
}
Team playerTeam = NetPlayer.localPlayer != null
? NetPlayer.localPlayer.myTeam
: GameManager.MyTeam;
Team opponentTeam = playerTeam == Team.Red ? Team.Blue : Team.Red;
if (GameManager.instance.SelectedTeam != playerTeam)
GameManager.instance.SwitchTeams();
aiController.Setup(opponentTeam);
}
}
@@ -0,0 +1,2 @@
fileFormatVersion: 2
guid: 304204825fc486545a7a9bd7dd232861
+13
View File
@@ -4,6 +4,19 @@ using UnityEngine;
public class Goal : NetworkBehaviour public class Goal : NetworkBehaviour
{ {
public Team team; public Team team;
public static Goal RedGoal,BlueGoal;
void Awake()
{
if(team == Team.Red){
RedGoal = this;
}else{
BlueGoal = this;
}
}
void OnTriggerEnter2D(Collider2D collision) void OnTriggerEnter2D(Collider2D collision)
{ {
if(!isServer){return;} if(!isServer){return;}
+285 -8
View File
@@ -1,5 +1,6 @@
using System; using System;
using System.Collections; using System.Collections;
using System.Globalization;
using System.IO; using System.IO;
using System.Text; using System.Text;
#if UNITY_EDITOR #if UNITY_EDITOR
@@ -13,7 +14,7 @@ using UnityEngine.UI;
public class LoginManager : MonoBehaviour public class LoginManager : MonoBehaviour
{ {
public const string AuthBaseUrl = "https://kickkingsapi.playpoolstudios.com"; public const string AuthBaseUrl = "https://kkapi.playpoolstudios.com";
const string PlayerPrefsAuthKey = "WalkInvest.AuthToken"; const string PlayerPrefsAuthKey = "WalkInvest.AuthToken";
const int MIN_USERNAME_LENGTH = 3; const int MIN_USERNAME_LENGTH = 3;
@@ -27,12 +28,31 @@ public class LoginManager : MonoBehaviour
[SerializeField] private Button btnLogin; [SerializeField] private Button btnLogin;
[Header("Register")] [Header("Register")]
[SerializeField] private TMP_InputField usernameInputRegister; [SerializeField] private TMP_InputField usernameInputRegister;
[SerializeField] private TMP_InputField emailInputRegister;
[SerializeField] private TMP_InputField passwordInputRegister; [SerializeField] private TMP_InputField passwordInputRegister;
[SerializeField] private Button btnRegister; [SerializeField] private Button btnRegister;
[Header("UI")] [Header("UI")]
[SerializeField] private TMP_Text error_txt; [SerializeField] private TMP_Text error_txt;
[Header("Server messages (GET /table_settings, no auth)")]
[Header("Update")]
[SerializeField] private GameObject serverUpdatePanel;
[SerializeField] private Button btnServerUpdate;
[Tooltip("Opened when the user taps Update on the forced-update panel (e.g. Telegram channel).")]
public string telegramUpdateChannelUrl = "";
[Header("Error")]
[SerializeField] private GameObject errorPanel;
[SerializeField] private TMP_Text serverErrorMessageTxt;
[SerializeField] private Button btnErrorClose;
[Header("Warning")]
[SerializeField] private GameObject warningPanel;
[SerializeField] private TMP_Text serverWarningMessageTxt;
[SerializeField] private Button btnWarningClose;
bool _authInProgress; bool _authInProgress;
public static string AuthToken { get; private set; } public static string AuthToken { get; private set; }
@@ -85,6 +105,7 @@ public class LoginManager : MonoBehaviour
void Awake() void Awake()
{ {
error_txt.text = ""; error_txt.text = "";
HideServerMessagePanels();
AuthToken = PlayerPrefs.GetString(PlayerPrefsAuthKey, ""); AuthToken = PlayerPrefs.GetString(PlayerPrefsAuthKey, "");
if(instance !=null){ if(instance !=null){
@@ -102,6 +123,26 @@ public class LoginManager : MonoBehaviour
{ {
btnLogin.onClick.AddListener(OnLogin); btnLogin.onClick.AddListener(OnLogin);
btnRegister.onClick.AddListener(OnRegister); btnRegister.onClick.AddListener(OnRegister);
if (btnServerUpdate != null)
btnServerUpdate.onClick.AddListener(OnServerUpdateClick);
if (btnErrorClose != null)
btnErrorClose.onClick.AddListener(OnServerErrorCloseClick);
SetBusy(true);
StartCoroutine(StartupSequenceCoroutine());
}
IEnumerator StartupSequenceCoroutine()
{
bool mayContinue = false;
yield return StartCoroutine(CoApplyTableSettingsGate(r => mayContinue = r));
if (!mayContinue)
{
// Blocked by update or error panel — keep login UI disabled.
SetBusy(false);
yield break;
}
#if UNITY_EDITOR #if UNITY_EDITOR
// Dev: log in with clone-aware credentials instead of resuming a saved session. // Dev: log in with clone-aware credentials instead of resuming a saved session.
@@ -117,12 +158,12 @@ public class LoginManager : MonoBehaviour
string loginJson = "{\"username\":\"" + EscapeJsonString(devUser) + "\",\"password\":\"" + EscapeJsonString(devPass) + "\"}"; string loginJson = "{\"username\":\"" + EscapeJsonString(devUser) + "\",\"password\":\"" + EscapeJsonString(devPass) + "\"}";
// StartCoroutine(AuthPostCoroutine(AuthBaseUrl + "/auth/login", loginJson, "Signed in.")); // StartCoroutine(AuthPostCoroutine(AuthBaseUrl + "/auth/login", loginJson, "Signed in."));
SetBusy(false);
#else #else
if (!string.IsNullOrEmpty(AuthToken)) if (!string.IsNullOrEmpty(AuthToken))
{ yield return StartCoroutine(ResumeSessionCoroutine());
SetBusy(true); else
StartCoroutine(ResumeSessionCoroutine()); SetBusy(false);
}
#endif #endif
} }
@@ -231,13 +272,21 @@ public class LoginManager : MonoBehaviour
if (_authInProgress) return; if (_authInProgress) return;
string username = usernameInputRegister.text; string username = usernameInputRegister.text;
string email = emailInputRegister != null ? emailInputRegister.text : "";
string password = passwordInputRegister.text; string password = passwordInputRegister.text;
if (string.IsNullOrEmpty(username) || string.IsNullOrEmpty(password)) if (string.IsNullOrEmpty(username) || string.IsNullOrEmpty(email) || string.IsNullOrEmpty(password))
{ {
error_txt.text = "Please fill in all fields"; error_txt.text = "Please fill in all fields";
return; return;
} }
email = email.Trim().ToLowerInvariant();
if (!IsValidEmailFormat(email))
{
error_txt.text = "Please enter a valid email address";
return;
}
if (username.Length < MIN_USERNAME_LENGTH || username.Length > MAX_USERNAME_LENGTH) if (username.Length < MIN_USERNAME_LENGTH || username.Length > MAX_USERNAME_LENGTH)
{ {
error_txt.text = "Username must be between " + MIN_USERNAME_LENGTH + " and " + MAX_USERNAME_LENGTH + " characters"; error_txt.text = "Username must be between " + MIN_USERNAME_LENGTH + " and " + MAX_USERNAME_LENGTH + " characters";
@@ -250,11 +299,36 @@ public class LoginManager : MonoBehaviour
return; return;
} }
// Server register endpoint accepts username + password only (email field is optional UI-only). string json = "{\"username\":\"" + EscapeJsonString(username) + "\",\"email\":\"" + EscapeJsonString(email) + "\",\"password\":\"" + EscapeJsonString(password) + "\"}";
string json = "{\"username\":\"" + EscapeJsonString(username) + "\",\"password\":\"" + EscapeJsonString(password) + "\"}";
StartCoroutine(AuthPostCoroutine(AuthBaseUrl + "/auth/register", json, "Account created.")); StartCoroutine(AuthPostCoroutine(AuthBaseUrl + "/auth/register", json, "Account created."));
} }
static bool IsValidEmailFormat(string email)
{
if (string.IsNullOrEmpty(email))
return false;
int at = email.IndexOf('@');
if (at <= 0)
return false;
if (email.IndexOf('@', at + 1) >= 0)
return false;
string domain = email.Substring(at + 1);
int dot = domain.LastIndexOf('.');
if (dot <= 0 || dot >= domain.Length - 1)
return false;
for (int i = 0; i < email.Length; i++)
{
if (char.IsWhiteSpace(email[i]))
return false;
}
return true;
}
static string EscapeJsonString(string s) static string EscapeJsonString(string s)
{ {
if (string.IsNullOrEmpty(s)) return s; if (string.IsNullOrEmpty(s)) return s;
@@ -325,6 +399,149 @@ public class LoginManager : MonoBehaviour
SetBusy(false); SetBusy(false);
} }
void HideServerMessagePanels()
{
if (serverUpdatePanel != null) serverUpdatePanel.SetActive(false);
if (errorPanel != null) errorPanel.SetActive(false);
if (warningPanel != null) warningPanel.SetActive(false);
}
void OnServerUpdateClick()
{
if (!string.IsNullOrWhiteSpace(telegramUpdateChannelUrl))
Application.OpenURL(telegramUpdateChannelUrl.Trim());
}
void OnServerErrorCloseClick()
{
#if UNITY_EDITOR
EditorApplication.ExitPlaymode();
#else
Application.Quit();
#endif
}
/// <summary>
/// GET <c>/table_settings</c> (public) and applies version / error / warning gates.
/// Callback receives <c>true</c> when login may continue to the main menu.
/// </summary>
IEnumerator CoApplyTableSettingsGate(Action<bool> onComplete)
{
CupidTableSettings table = null;
yield return StartCoroutine(FetchTableSettingsCoroutine(t => table = t));
if (table == null)
{
onComplete?.Invoke(true);
yield break;
}
if (IsClientBelowRequiredVersion(table.version))
{
if (serverUpdatePanel != null)
serverUpdatePanel.SetActive(true);
onComplete?.Invoke(false);
yield break;
}
if (!string.IsNullOrWhiteSpace(table.error_msg))
{
if (serverErrorMessageTxt != null)
serverErrorMessageTxt.text = table.error_msg.Trim();
if (errorPanel != null)
errorPanel.SetActive(true);
onComplete?.Invoke(false);
yield break;
}
if (!string.IsNullOrWhiteSpace(table.warning_msg))
yield return CoWaitForWarningDismiss(table.warning_msg.Trim());
onComplete?.Invoke(true);
}
IEnumerator FetchTableSettingsCoroutine(Action<CupidTableSettings> onResult)
{
string url = AuthBaseUrl + "/table_settings";
using (var request = UnityWebRequest.Get(url))
{
request.downloadHandler = new DownloadHandlerBuffer();
yield return request.SendWebRequest();
string text = request.downloadHandler != null ? request.downloadHandler.text : "";
if (request.result != UnityWebRequest.Result.Success &&
request.result != UnityWebRequest.Result.ProtocolError)
{
onResult?.Invoke(null);
yield break;
}
if (request.responseCode < 200 || request.responseCode >= 300 || string.IsNullOrWhiteSpace(text))
{
onResult?.Invoke(null);
yield break;
}
try
{
CupidTableSettings parsed = JsonUtility.FromJson<CupidTableSettings>(text);
onResult?.Invoke(parsed);
}
catch (Exception e)
{
Logger.Log("table_settings JSON error: " + e.Message + " body=" + text);
onResult?.Invoke(null);
}
}
}
static bool IsClientBelowRequiredVersion(string requiredVersion)
{
if (string.IsNullOrWhiteSpace(requiredVersion))
return false;
if (!TryParseVersionFloat(requiredVersion, out float required))
return false;
if (!TryParseVersionFloat(Application.version, out float client))
return false;
return client < required;
}
static bool TryParseVersionFloat(string version, out float value)
{
value = 0f;
if (string.IsNullOrWhiteSpace(version))
return false;
return float.TryParse(version.Trim(), NumberStyles.Float, CultureInfo.InvariantCulture, out value);
}
IEnumerator CoWaitForWarningDismiss(string message)
{
if (serverWarningMessageTxt != null)
serverWarningMessageTxt.text = message;
if (warningPanel != null)
warningPanel.SetActive(true);
bool dismissed = false;
void OnDismiss()
{
dismissed = true;
if (warningPanel != null)
warningPanel.SetActive(false);
}
if (btnWarningClose != null)
{
btnWarningClose.onClick.RemoveListener(OnDismiss);
btnWarningClose.onClick.AddListener(OnDismiss);
}
yield return new WaitUntil(() => dismissed);
if (btnWarningClose != null)
btnWarningClose.onClick.RemoveListener(OnDismiss);
}
static void ApplyUserData(UserData u) static void ApplyUserData(UserData u)
{ {
_currentUser = u; _currentUser = u;
@@ -397,6 +614,12 @@ public class LoginManager : MonoBehaviour
StartCoroutine(PurchaseRcCoroutine(packId, onComplete)); StartCoroutine(PurchaseRcCoroutine(packId, onComplete));
} }
/// <summary>POST /auth/ping-report with <c>{"match_id":123,"ping":42}</c>. Callback (success, errorOrNull, reportOrNull).</summary>
public void ReportPing(int matchId, int ping, Action<bool, string, PingReportData> onComplete)
{
StartCoroutine(ReportPingCoroutine(matchId, ping, onComplete));
}
IEnumerator PurchaseRcCoroutine(string packId, Action<bool, string> onComplete) IEnumerator PurchaseRcCoroutine(string packId, Action<bool, string> onComplete)
{ {
if (string.IsNullOrEmpty(AuthToken)) if (string.IsNullOrEmpty(AuthToken))
@@ -470,6 +693,59 @@ public class LoginManager : MonoBehaviour
} }
} }
IEnumerator ReportPingCoroutine(int matchId, int ping, Action<bool, string, PingReportData> onComplete)
{
if (string.IsNullOrEmpty(AuthToken))
{
onComplete?.Invoke(false, "Not signed in", null);
yield break;
}
string json = "{\"match_id\":" + matchId + ",\"ping\":" + ping + "}";
string url = AuthBaseUrl + "/auth/ping-report";
using (var request = new UnityWebRequest(url, UnityWebRequest.kHttpVerbPOST))
{
byte[] bodyRaw = Encoding.UTF8.GetBytes(json);
request.uploadHandler = new UploadHandlerRaw(bodyRaw);
request.downloadHandler = new DownloadHandlerBuffer();
request.SetRequestHeader("Content-Type", "application/json");
request.SetRequestHeader("Authorization", "Bearer " + AuthToken);
yield return request.SendWebRequest();
string text = request.downloadHandler != null ? request.downloadHandler.text : "";
if (request.result != UnityWebRequest.Result.Success &&
request.result != UnityWebRequest.Result.ProtocolError)
{
onComplete?.Invoke(false, string.IsNullOrEmpty(request.error) ? "Network error" : request.error, null);
yield break;
}
if (request.responseCode < 200 || request.responseCode >= 300)
{
onComplete?.Invoke(false, string.IsNullOrEmpty(text) ? "Request failed (" + request.responseCode + ")" : text, null);
yield break;
}
if (string.IsNullOrEmpty(text))
{
onComplete?.Invoke(false, "Empty response from server", null);
yield break;
}
PingReportApiResponse resp = JsonUtility.FromJson<PingReportApiResponse>(text);
if (resp != null && resp.ok && resp.report != null)
onComplete?.Invoke(true, null, resp.report);
else
{
string err = resp != null && !string.IsNullOrEmpty(resp.error) ? resp.error : "Ping report failed";
onComplete?.Invoke(false, err, null);
}
}
}
IEnumerator FetchUserDataCoroutine(Action<bool, string, UserData> onComplete, bool applyToStatic) IEnumerator FetchUserDataCoroutine(Action<bool, string, UserData> onComplete, bool applyToStatic)
{ {
if (string.IsNullOrEmpty(AuthToken)) if (string.IsNullOrEmpty(AuthToken))
@@ -522,4 +798,5 @@ public class LoginManager : MonoBehaviour
} }
} }
} }
} }
+47
View File
@@ -25,11 +25,15 @@ public class MainMenuManager : MonoBehaviour
public GameObject gameModesScreen; public GameObject gameModesScreen;
public GameObject dummyBuyScreen; public GameObject dummyBuyScreen;
public GameObject withdrawalScreen; public GameObject withdrawalScreen;
public GameObject settingsScreen;
[Header("Play")] [Header("Play")]
public Button btnPlay; public Button btnPlay;
public Button btnTutorial;
public TMP_Text rcPlayText; public TMP_Text rcPlayText;
public TMP_Text entryFeeTxt; public TMP_Text entryFeeTxt;
public TMP_Text rcPrizeTxt; public TMP_Text rcPrizeTxt;
[SerializeField] string tutorialGameScene = GameTutorialManager.DefaultGameSceneName;
[Header("Dummy Buy")] [Header("Dummy Buy")]
public Button btnBuyUsd5; public Button btnBuyUsd5;
@@ -99,6 +103,8 @@ public class MainMenuManager : MonoBehaviour
btnPaste.onClick.AddListener(OnPasteFromClipboard); btnPaste.onClick.AddListener(OnPasteFromClipboard);
btnPlay.onClick.AddListener(OnPlay); btnPlay.onClick.AddListener(OnPlay);
if (btnTutorial != null && btnTutorial != btnPlay)
btnTutorial.onClick.AddListener(OnPlayTutorial);
toggleSfx.onToggleValueChanged.AddListener(OnToggleSfx); toggleSfx.onToggleValueChanged.AddListener(OnToggleSfx);
toggleMusic.onToggleValueChanged.AddListener(OnToggleMusic); toggleMusic.onToggleValueChanged.AddListener(OnToggleMusic);
@@ -114,6 +120,8 @@ public class MainMenuManager : MonoBehaviour
LoginManager.OnUserDataUpdated -= OnUserUpdated; LoginManager.OnUserDataUpdated -= OnUserUpdated;
toggleSfx.onToggleValueChanged.RemoveListener(OnToggleSfx); toggleSfx.onToggleValueChanged.RemoveListener(OnToggleSfx);
toggleMusic.onToggleValueChanged.RemoveListener(OnToggleMusic); toggleMusic.onToggleValueChanged.RemoveListener(OnToggleMusic);
if (btnTutorial != null && btnTutorial != btnPlay)
btnTutorial.onClick.RemoveListener(OnPlayTutorial);
} }
void OnToggleSfx(bool isOn) void OnToggleSfx(bool isOn)
@@ -146,6 +154,32 @@ public class MainMenuManager : MonoBehaviour
CupidLobby.instance.Matchmake(); CupidLobby.instance.Matchmake();
} }
public void OnPlayTutorial()
{
if (LoginManager.CurrentUser == null)
{
Debug.LogError("Tutorial blocked: user profile not loaded.");
return;
}
if (LevelLoadManager.instance == null)
{
Debug.LogError("Tutorial blocked: LevelLoadManager is missing.");
return;
}
StartCoroutine(CoLaunchTutorial());
}
IEnumerator CoLaunchTutorial()
{
MatchmadePlayer myPlayer = GameTutorialManager.CreateMyPlayerFromUser(LoginManager.CurrentUser);
MatchmadePlayer cpuPlayer = GameTutorialManager.CreateCpuOpponent();
yield return GameTutorialManager.CoFetchPlayerL10(myPlayer);
GameTutorialManager.PrepareLaunch(myPlayer, cpuPlayer);
LevelLoadManager.LoadLevel(tutorialGameScene);
}
void OnCryptoAddressChanged(string value) void OnCryptoAddressChanged(string value)
{ {
PlayerPrefs.SetString(CryptoAddressPrefsKey, value ?? string.Empty); PlayerPrefs.SetString(CryptoAddressPrefsKey, value ?? string.Empty);
@@ -306,6 +340,7 @@ public class MainMenuManager : MonoBehaviour
gameModesScreen.SetActive(false); gameModesScreen.SetActive(false);
dummyBuyScreen.SetActive(false); dummyBuyScreen.SetActive(false);
withdrawalScreen.SetActive(false); withdrawalScreen.SetActive(false);
settingsScreen.SetActive(false);
} }
public void ShowGameModesScreen(){ public void ShowGameModesScreen(){
@@ -314,6 +349,7 @@ public class MainMenuManager : MonoBehaviour
gameModesScreen.SetActive(true); gameModesScreen.SetActive(true);
dummyBuyScreen.SetActive(false); dummyBuyScreen.SetActive(false);
withdrawalScreen.SetActive(false); withdrawalScreen.SetActive(false);
settingsScreen.SetActive(false);
} }
public void ShowDummyBuyScreen(){ public void ShowDummyBuyScreen(){
@@ -322,6 +358,7 @@ public class MainMenuManager : MonoBehaviour
gameModesScreen.SetActive(false); gameModesScreen.SetActive(false);
dummyBuyScreen.SetActive(true); dummyBuyScreen.SetActive(true);
withdrawalScreen.SetActive(false); withdrawalScreen.SetActive(false);
settingsScreen.SetActive(false);
} }
public void ShowWithdrawalScreen(){ public void ShowWithdrawalScreen(){
@@ -330,7 +367,17 @@ public class MainMenuManager : MonoBehaviour
gameModesScreen.SetActive(false); gameModesScreen.SetActive(false);
dummyBuyScreen.SetActive(false); dummyBuyScreen.SetActive(false);
withdrawalScreen.SetActive(true); withdrawalScreen.SetActive(true);
settingsScreen.SetActive(false);
UpdateWithdrawalStatus(); UpdateWithdrawalStatus();
} }
public void ShowSettingsScreen(){
statsPanel.SetActive(false);
mainMenuScreen.SetActive(false);
gameModesScreen.SetActive(false);
dummyBuyScreen.SetActive(false);
withdrawalScreen.SetActive(false);
settingsScreen.SetActive(true);
}
} }
+58 -4
View File
@@ -17,9 +17,11 @@ public class NetManager : NetworkManager
static bool s_IntentionalClientDisconnect; static bool s_IntentionalClientDisconnect;
public static NetManager instance;
public override void Awake() public override void Awake()
{ {
base.Awake(); base.Awake();
instance = this;
Transport.active.OnClientError += OnTransportClientError; Transport.active.OnClientError += OnTransportClientError;
} }
@@ -27,6 +29,35 @@ public class NetManager : NetworkManager
{ {
if (Transport.active != null) if (Transport.active != null)
Transport.active.OnClientError -= OnTransportClientError; Transport.active.OnClientError -= OnTransportClientError;
if (NetworkServer.active || NetworkClient.active)
StopNetworkingForSceneChange();
}
/// <summary>
/// Fully tears down Mirror before loading another scene. Required for tutorial host mode;
/// <see cref="NetworkManager.StopClient"/> alone leaves the server running.
/// </summary>
public static void StopNetworkingForSceneChange()
{
MarkIntentionalClientDisconnect();
NetworkManager manager = singleton != null ? singleton : NetworkManager.singleton;
if (manager != null)
{
if (NetworkServer.active && NetworkClient.active)
manager.StopHost();
else if (NetworkClient.active)
manager.StopClient();
else if (NetworkServer.active)
manager.StopServer();
return;
}
if (NetworkClient.active)
NetworkClient.Shutdown();
if (NetworkServer.active)
NetworkServer.Shutdown();
} }
static void OnTransportClientError(TransportError error, string reason) static void OnTransportClientError(TransportError error, string reason)
@@ -114,6 +145,7 @@ public class NetManager : NetworkManager
{ {
Application.logMessageReceived -= ForwardMirrorServerLogToLogger; Application.logMessageReceived -= ForwardMirrorServerLogToLogger;
ReplayRecorder.StopAndFlush();
GameManager.ReportDedicatedMatchRoomClosed(); GameManager.ReportDedicatedMatchRoomClosed();
base.OnStopServer(); base.OnStopServer();
} }
@@ -131,7 +163,10 @@ public class NetManager : NetworkManager
{ {
base.OnClientDisconnect(); base.OnClientDisconnect();
Logger.Log("Client disconnected"); Logger.Log("Client disconnected");
if (ShouldReconnect()) // Mirror raises OnDisconnectedEvent before clearing ConnectState, so
// NetworkClient.isConnected is still true here on involuntary drops.
// Gate on policy flags only; teardown wait happens in the reconnect loop.
if (CanAttemptReconnect())
{ {
if (reconnectCoroutine == null) if (reconnectCoroutine == null)
reconnectCoroutine = StartCoroutine(ReconnectLoopCoroutine()); reconnectCoroutine = StartCoroutine(ReconnectLoopCoroutine());
@@ -175,6 +210,12 @@ public class NetManager : NetworkManager
SetReconnectCanvasVisible(true); SetReconnectCanvasVisible(true);
reopenRequestedThisDisconnect = false; reopenRequestedThisDisconnect = false;
reopenRequestInFlight = false; reopenRequestInFlight = false;
// Wait until Mirror finishes OnClientDisconnectInternal (clears Connected
// then Shutdown). Without this, ShouldReconnect() fails immediately.
while (NetworkClient.isConnected || NetworkClient.active)
yield return null;
float reconnectStartedAt = Time.realtimeSinceStartup; float reconnectStartedAt = Time.realtimeSinceStartup;
float initialWaitEnd = Time.realtimeSinceStartup + InitialReconnectDelaySeconds; float initialWaitEnd = Time.realtimeSinceStartup + InitialReconnectDelaySeconds;
while (ShouldReconnect() && Time.realtimeSinceStartup < initialWaitEnd) while (ShouldReconnect() && Time.realtimeSinceStartup < initialWaitEnd)
@@ -211,20 +252,32 @@ public class NetManager : NetworkManager
SetReconnectCanvasVisible(false); SetReconnectCanvasVisible(false);
} }
bool ShouldReconnect() /// <summary>
/// Policy checks that are safe during Mirror's disconnect callback
/// (when <see cref="NetworkClient.isConnected"/> may still be true).
/// </summary>
bool CanAttemptReconnect()
{ {
if (s_IntentionalClientDisconnect) if (s_IntentionalClientDisconnect)
return false; return false;
if (NetworkServer.active) if (NetworkServer.active)
return false; return false;
if (NetworkClient.isConnected)
return false;
if (GameManager.instance != null && GameManager.instance.isGameEnded) if (GameManager.instance != null && GameManager.instance.isGameEnded)
return false; return false;
return true; return true;
} }
bool ShouldReconnect()
{
if (!CanAttemptReconnect())
return false;
if (NetworkClient.isConnected)
return false;
return true;
}
IEnumerator CoRequestReopenForCurrentPort() IEnumerator CoRequestReopenForCurrentPort()
{ {
reopenRequestInFlight = true; reopenRequestInFlight = true;
@@ -279,4 +332,5 @@ public class NetManager : NetworkManager
reopenRequestInFlight = false; reopenRequestInFlight = false;
} }
} }
+47 -11
View File
@@ -8,6 +8,7 @@ using UnityEngine.InputSystem;
#endif #endif
public class NetPlayer : NetworkBehaviour public class NetPlayer : NetworkBehaviour
{ {
const float PingReportIntervalSeconds = 30f;
[SyncVar] [SyncVar]
public int userId; public int userId;
@@ -36,6 +37,9 @@ public class NetPlayer : NetworkBehaviour
SetMyData(GameManager.MyTeam == Team.Red ? GameManager.RedPlayer.UserId : GameManager.BluePlayer.UserId); SetMyData(GameManager.MyTeam == Team.Red ? GameManager.RedPlayer.UserId : GameManager.BluePlayer.UserId);
#endif #endif
TeamSpecificEffects.instance.SetTeamSpecificEffects(myTeam); TeamSpecificEffects.instance.SetTeamSpecificEffects(myTeam);
if (GameManager.instance != null)
GameManager.instance.OnLocalPlayerJoinedMatch();
} }
void SetMyData(int uid){ void SetMyData(int uid){
@@ -96,6 +100,7 @@ public class NetPlayer : NetworkBehaviour
bool isDragging; bool isDragging;
Vector2 lastDragScreenPosition; Vector2 lastDragScreenPosition;
bool serverDragActive; bool serverDragActive;
Coroutine pingReportCoroutine;
#region EMOTES #region EMOTES
public void SendTextEmote(string txtName){ public void SendTextEmote(string txtName){
@@ -155,10 +160,16 @@ public class NetPlayer : NetworkBehaviour
if(isLocalPlayer){ if(isLocalPlayer){
localPlayer = this; localPlayer = this;
SetupInputPanel(); SetupInputPanel();
pingReportCoroutine = StartCoroutine(CoReportPingPeriodically());
} }
} }
void OnDestroy(){ void OnDestroy(){
if (pingReportCoroutine != null)
{
StopCoroutine(pingReportCoroutine);
pingReportCoroutine = null;
}
if(localPlayer == this){ if(localPlayer == this){
localPlayer = null; localPlayer = null;
} }
@@ -419,29 +430,30 @@ public class NetPlayer : NetworkBehaviour
/// Request a rematch with the opponent. /// Request a rematch with the opponent.
/// </summary> /// </summary>
public void RequestRematch(){ public void RequestRematch(){
int maxBetLimitCoins = GameOverCanvas.GetPersonalBetLimit();
if(isServer){ if(isServer){
GameOverCanvas.instance.OnRematchRequested(); GameOverCanvas.instance.OnRematchRequested(maxBetLimitCoins);
RpcRequestRematch(); RpcRequestRematch(maxBetLimitCoins);
}else{ }else{
CmdRequestRematch(); CmdRequestRematch(maxBetLimitCoins);
} }
} }
[Command] [Command]
void CmdRequestRematch(){ void CmdRequestRematch(int maxBetLimitCoins){
Logger.Log("Rematch requested"); Logger.Log("Rematch requested, max bet limit coins: " + maxBetLimitCoins);
if(isServerOnly){ if(isServerOnly){
//server //server
}else{ }else{
GameOverCanvas.instance.OnRematchRequested(); GameOverCanvas.instance.OnRematchRequested(maxBetLimitCoins);
} }
RpcRequestRematch(); RpcRequestRematch(maxBetLimitCoins);
} }
[ClientRpc] [ClientRpc]
void RpcRequestRematch(){ void RpcRequestRematch(int maxBetLimitCoins){
GameOverCanvas.instance.OnRematchRequested(); GameOverCanvas.instance.OnRematchRequested(maxBetLimitCoins);
} }
@@ -530,8 +542,7 @@ public class NetPlayer : NetworkBehaviour
Cupid.RoomPort = branch.Port; Cupid.RoomPort = branch.Port;
LoginManager.SetMatchYourTeam(branch.your_team); LoginManager.SetMatchYourTeam(branch.your_team);
GameManager.instance.StopClient(); LevelLoadManager.instance.Leave("Game");
LevelLoadManager.LoadLevel("Game");
} }
void OnRematchCancelledServer(){ void OnRematchCancelledServer(){
@@ -552,4 +563,29 @@ public class NetPlayer : NetworkBehaviour
GameOverCanvas.instance.OnRematchCancelled(); GameOverCanvas.instance.OnRematchCancelled();
} }
IEnumerator CoReportPingPeriodically()
{
var wait = new WaitForSecondsRealtime(PingReportIntervalSeconds);
while (isLocalPlayer)
{
yield return wait;
if (!NetworkClient.active || !NetworkClient.isConnected)
continue;
if (LoginManager.instance == null || string.IsNullOrEmpty(LoginManager.AuthToken))
continue;
int matchId = GameManager.DedicatedMatchId;
if (matchId <= 0)
continue;
int pingMs = Mathf.Max(0, Mathf.RoundToInt((float)(NetworkTime.rtt * 1000.0)));
LoginManager.instance.ReportPing(matchId, pingMs, (ok, err, report) =>
{
if (!ok && !string.IsNullOrEmpty(err))
Logger.Log("Ping report failed: " + err);
});
}
}
} }
+1
View File
@@ -135,6 +135,7 @@ public class Puck : NetworkBehaviour
if (AudioManager.instance != null){ if (AudioManager.instance != null){
AudioManager.instance.PlayPuckHit(vol); AudioManager.instance.PlayPuckHit(vol);
if(isServer){ if(isServer){
ReplayRecorder.RecordHit("puck_puck", vol, this);
RpcPuckHitAudio(vol); RpcPuckHitAudio(vol);
} }
} }
+8
View File
@@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 9cff4a867ddc05341bf42777b654509a
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:
+291
View File
@@ -0,0 +1,291 @@
# Match Replay JSON Format
Guide for implementing the admin-panel replay viewer. Files are written by the Unity dedicated server (and practice host) to disk only.
## Where files live
Written next to the match log with the **same basename**, only the extension differs:
```
{ApplicationDirectory}/Logs/{matchId}.txt ← match log
{ApplicationDirectory}/Logs/{matchId}.json ← replay
```
| Match type | `matchId` | Example pair |
|------------|-----------|--------------|
| Ranked / dedicated | Positive matchmaker id | `Logs/228.txt` + `Logs/228.json` |
| Practice / tutorial | Negative unix timestamp | `Logs/-1769539200.txt` + `Logs/-1769539200.json` |
Admin panel: given a log at `Logs/{id}.txt`, load `Logs/{id}.json` beside it.
## Top-level object
```json
{
"version": 1,
"matchId": 228,
"isPractice": false,
"fixedDeltaTime": 0.02,
"duration": 184.32,
"entities": [ /* ... */ ],
"frames": [ /* ... */ ],
"events": [ /* ... */ ]
}
```
| Field | Type | Description |
|-------|------|-------------|
| `version` | int | Schema version. Currently `1`. |
| `matchId` | int | Match id (positive = ranked, negative = practice). |
| `isPractice` | bool | `true` for localhost practice / tutorial host. |
| `fixedDeltaTime` | float | Physics step used while recording (typically `0.02` → ~50 Hz). |
| `duration` | float | Length of the recording in seconds (`t` of last sample / end). |
| `entities` | array | Ball + pucks. Order defines pose array indices in every frame. |
| `frames` | array | Time-ordered pose samples (~every FixedUpdate). |
| `events` | array | Time-ordered discrete events (hits, goals, resets). |
Time `t` everywhere is **seconds since recording start** (match start), not wall-clock UTC.
---
## Entities
```json
{ "id": 0, "type": "ball", "team": "" }
{ "id": 1, "type": "puck", "team": "Red" }
{ "id": 2, "type": "puck", "team": "Blue" }
```
| Field | Type | Values |
|-------|------|--------|
| `id` | int | Stable index `0 .. N-1`. Matches array index in each frames `x`/`y`/`vx`/`vy`. |
| `type` | string | `"ball"` or `"puck"` |
| `team` | string | `"Red"`, `"Blue"`, or `""` for ball |
Entity list is fixed for the whole file. **Index `i` in a frames pose arrays always refers to `entities[i]`.**
Typical order: ball first, then pucks sorted by team then spawn position.
---
## Frames (motion samples)
```json
{
"t": 12.40,
"x": [0.0, 1.2, -0.5],
"y": [0.1, -0.3, 2.0],
"vx": [0.0, 3.1, -1.0],
"vy": [0.2, 0.0, 0.5]
}
```
| Field | Type | Description |
|-------|------|-------------|
| `t` | float | Sample time in seconds (monotonic, increasing). |
| `x`, `y` | float[] | World position per entity (Unity 2D world units). |
| `vx`, `vy` | float[] | Linear velocity per entity at that sample (world units / second). |
- Array length always equals `entities.length`.
- Samples are dense (~`1 / fixedDeltaTime` Hz). Do **not** treat them as render frames.
### Coordinate system
Unity 2D world space:
- Origin at field center
- `+X` right, `+Y` up (as in Unity)
- Scale matches the in-game pitch (see game `fieldSize` / art for admin canvas mapping)
---
## Events
```json
{ "t": 12.4, "type": "hit", "kind": "ball_wall", "vol": 0.6, "id": 0, "team": "", "redScore": 0, "blueScore": 0, "kickoff": false }
{ "t": 30.1, "type": "goal", "kind": "", "vol": 0, "id": -1, "team": "Blue", "redScore": 1, "blueScore": 0, "kickoff": false }
{ "t": 32.2, "type": "reset", "kind": "", "vol": 0, "id": -1, "team": "", "redScore": 0, "blueScore": 0, "kickoff": false }
```
All event objects share the same fields (Unity `JsonUtility` shape). Unused fields are empty / zero / `-1`.
| Field | Used by | Description |
|-------|---------|-------------|
| `t` | all | Event time in seconds. |
| `type` | all | `"hit"` \| `"goal"` \| `"reset"` |
| `kind` | `hit` | `"puck_puck"` \| `"ball_puck"` \| `"ball_wall"` |
| `vol` | `hit` | SFX volume `0..1` (from relative impact speed). |
| `id` | `hit` | Entity id involved (spatial cue). `-1` if unknown. |
| `team` | `goal` | **Conceding** side / goal owner (`"Red"` or `"Blue"`). The other team scored. |
| `redScore` | `goal` | Score after this goal. |
| `blueScore` | `goal` | Score after this goal. |
| `kickoff` | `goal`, `reset` | Kickoff-goal / kickoff-style reset when `true`. |
### Event semantics
| `type` | Meaning for the viewer |
|--------|-------------------------|
| `hit` | Play collision SFX at `vol`. Optional: flash near entity `id`. |
| `goal` | Goal scored against `team`. Update scoreboard to `redScore`/`blueScore`. Play goal SFX. **Discontinuity** — do not interpolate motion across this time. |
| `reset` | Pieces are lerping / teleporting back. **Discontinuity** — snap poses; do not blend across. |
First-to-3 wins; a completed match usually ends shortly after a goal that makes a score `3`.
---
## Playback contract (required for smooth motion)
Recording is FixedUpdate (~50 Hz). Snapping happens if the viewer steps sample-by-sample without blending. Follow this:
### 1. Drive time with wall clock
```text
playbackTime += (deltaMs / 1000) * playbackSpeed
playbackTime = clamp(playbackTime, 0, duration)
```
Use `requestAnimationFrame` (or equivalent). Do **not** advance one JSON frame per rAF tick.
### 2. Interpolate poses between samples
Binary-search `frames` for neighbors where:
```text
frames[i].t <= playbackTime < frames[i+1].t
```
Then for each entity index `e`:
**Minimum (good):** linear lerp of `x`/`y`:
```text
u = (playbackTime - t0) / (t1 - t0)
x = lerp(x0[e], x1[e], u)
y = lerp(y0[e], y1[e], u)
```
**Recommended (smooth under acceleration):** cubic Hermite using velocities:
```text
dt = t1 - t0
u = (playbackTime - t0) / dt
u2 = u*u
u3 = u2*u
h00 = 2*u3 - 3*u2 + 1
h10 = u3 - 2*u2 + u
h01 = -2*u3 + 3*u2
h11 = u3 - u2
x = h00*x0 + h10*dt*vx0 + h01*x1 + h11*dt*vx1
y = h00*y0 + h10*dt*vy0 + h01*y1 + h11*dt*vy1
```
(Same for each entity index.)
### 3. Snap across discontinuities
Treat every `goal` and `reset` event as a cut:
- When `playbackTime` crosses that events `t`, **do not** interpolate from the previous sample across the cut.
- Seek to the frame at or immediately after `t` and snap positions.
Practical approach: build a sorted list of discontinuity times from events where `type === "goal" || type === "reset"`. If `t0` and `t1` straddle a discontinuity, snap to the post-cut sample instead of lerping.
### 4. Fire events once when crossed
Keep `lastEventIndex` (or last fired `t`). When `playbackTime` advances past an events `t`, fire it once:
- `hit` → SFX by `kind` / `vol`
- `goal` → score UI + goal audio
- `reset` → optional reset cue (usually silent)
On seek / scrub: reset event cursor; either skip SFX or replay only from the new time forward.
---
## Suggested viewer pipeline
```text
Load JSON
→ map entities to sprites (ball / red pucks / blue pucks)
→ sort events by t (already ordered, but verify)
→ each animation frame:
advance playbackTime
resolve poses (Hermite + discontinuity snaps)
draw entities
dispatch newly crossed events
```
### Seeking / scrubbing
1. Set `playbackTime` to the scrub value.
2. Find the nearest frame (or interpolate as above).
3. Recompute score from the last `goal` event with `t <= playbackTime` (else `00`).
4. Reset the event-fire cursor to that time so SFX dont spam.
### Scoreboard without scrubbing
Start at `00`. On each `goal` event, set scores from that events `redScore` / `blueScore`.
---
## Minimal TypeScript types
```ts
export interface ReplayFile {
version: number;
matchId: number;
isPractice: boolean;
fixedDeltaTime: number;
duration: number;
entities: ReplayEntity[];
frames: ReplayFrame[];
events: ReplayEvent[];
}
export interface ReplayEntity {
id: number;
type: "ball" | "puck" | string;
team: "Red" | "Blue" | "" | string;
}
export interface ReplayFrame {
t: number;
x: number[];
y: number[];
vx: number[];
vy: number[];
}
export interface ReplayEvent {
t: number;
type: "hit" | "goal" | "reset" | string;
kind: "puck_puck" | "ball_puck" | "ball_wall" | "" | string;
vol: number;
id: number; // entity id, or -1
team: "Red" | "Blue" | "" | string; // conceding team on goal
redScore: number;
blueScore: number;
kickoff: boolean;
}
```
---
## Checklist for a correct viewer
- [ ] Time driven by real elapsed time × speed, not frame index
- [ ] Poses interpolated between samples (Hermite preferred)
- [ ] No interpolation across `goal` / `reset`
- [ ] Entity index `i` always matches `entities[i]`
- [ ] Hit SFX use `kind` + `vol`
- [ ] Goal `team` means **conceding** side
- [ ] Practice files filtered via `isPractice` or negative `matchId`
## Out of scope (not in the JSON)
- Player names / user ids (use matchmaker / match API by `matchId` for ranked games)
- Camera / UI layout
- Launch aim lines / turn timer
- Network latency or client prediction
@@ -0,0 +1,7 @@
fileFormatVersion: 2
guid: 8cced32e9b154814b99db72a5ae58c70
TextScriptImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:
+8
View File
@@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: a1b2c3d4e5f60718293a4b5c6d7e8f90
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:
+61
View File
@@ -0,0 +1,61 @@
using System;
/// <summary>
/// Replay JSON DTOs for admin-panel playback.
/// Playback contract:
/// 1. Advance playbackTime with real time (scaled).
/// 2. Binary-search frames by t; Hermite-interpolate x/y using vx/vy between neighbors.
/// 3. On reset/goal events (discontinuities): snap to the sample at/after t — do not blend across.
/// 4. Fire SFX on hit/goal when playbackTime crosses event t.
/// </summary>
[Serializable]
public class ReplayFile
{
public int version = 1;
public int matchId;
/// <summary>True for localhost practice / tutorial host matches (no dedicated matchmaker id).</summary>
public bool isPractice;
public float fixedDeltaTime;
public float duration;
public ReplayEntity[] entities;
public ReplayFrame[] frames;
public ReplayEvent[] events;
}
[Serializable]
public class ReplayEntity
{
public int id;
/// <summary>"ball" or "puck"</summary>
public string type;
/// <summary>"Red", "Blue", or empty for ball</summary>
public string team;
}
[Serializable]
public class ReplayFrame
{
public float t;
public float[] x;
public float[] y;
public float[] vx;
public float[] vy;
}
[Serializable]
public class ReplayEvent
{
public float t;
/// <summary>"hit", "goal", or "reset"</summary>
public string type;
/// <summary>For hits: "puck_puck", "ball_puck", or "ball_wall"</summary>
public string kind;
public float vol;
/// <summary>Entity id for spatial cueing; -1 when N/A</summary>
public int id = -1;
/// <summary>For goals: conceding team ("Red"/"Blue")</summary>
public string team;
public int redScore;
public int blueScore;
public bool kickoff;
}
+11
View File
@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: b2c3d4e5f60718293a4b5c6d7e8f901a
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
+301
View File
@@ -0,0 +1,301 @@
using System;
using System.Collections.Generic;
using System.IO;
using Mirror;
using UnityEngine;
/// <summary>
/// Server-only match recorder. Samples poses every FixedUpdate; flushes JSON to disk on stop.
/// Admin playback must interpolate by time (Hermite using velocity) — never snap one FixedUpdate sample per render frame.
/// </summary>
public class ReplayRecorder : MonoBehaviour
{
public static ReplayRecorder Instance { get; private set; }
public static bool IsRecording => Instance != null && Instance._recording && !Instance._flushed;
bool _recording;
bool _flushed;
int _matchId;
bool _isPractice;
float _startFixedTime;
float _duration;
readonly List<ReplayEntity> _entities = new List<ReplayEntity>();
readonly List<Rigidbody2D> _bodies = new List<Rigidbody2D>();
readonly Dictionary<int, int> _instanceIdToEntityId = new Dictionary<int, int>();
readonly List<ReplayFrame> _frames = new List<ReplayFrame>();
readonly List<ReplayEvent> _events = new List<ReplayEvent>();
/// <returns>True if recording started (or already recording this session).</returns>
public static bool StartRecording(int matchId, GameManager gm)
{
if (!NetworkServer.active || gm == null)
return false;
if (Instance == null)
{
var go = new GameObject("ReplayRecorder");
DontDestroyOnLoad(go);
Instance = go.AddComponent<ReplayRecorder>();
}
Instance.Begin(matchId, gm);
return true;
}
public static void StopAndFlush()
{
if (Instance != null)
Instance.Flush();
}
public static void RecordHit(string kind, float vol, Component source)
{
if (!IsRecording)
return;
Instance.AddHit(kind, vol, source);
}
public static void RecordGoal(Team concedingTeam, int redScore, int blueScore, bool kickoff)
{
if (!IsRecording)
return;
Instance.AddEvent(new ReplayEvent
{
t = Instance.CurrentT(),
type = "goal",
kind = "",
vol = 0f,
id = -1,
team = concedingTeam.ToString(),
redScore = redScore,
blueScore = blueScore,
kickoff = kickoff
});
}
public static void RecordReset(bool kickoff)
{
if (!IsRecording)
return;
Instance.AddEvent(new ReplayEvent
{
t = Instance.CurrentT(),
type = "reset",
kind = "",
vol = 0f,
id = -1,
team = "",
redScore = 0,
blueScore = 0,
kickoff = kickoff
});
}
public static bool TryGetEntityId(Component source, out int entityId)
{
entityId = -1;
if (Instance == null || source == null)
return false;
return Instance._instanceIdToEntityId.TryGetValue(source.gameObject.GetInstanceID(), out entityId);
}
void Begin(int matchId, GameManager gm)
{
if (_recording && !_flushed)
Flush();
// Practice / tutorial host uses DedicatedMatchId 0 — mint a unique id so files don't overwrite.
_isPractice = matchId <= 0 || GameTutorialManager.tutorialModeEnabled;
if (matchId <= 0)
matchId = GeneratePracticeMatchId();
_matchId = matchId;
_recording = true;
_flushed = false;
_startFixedTime = Time.fixedTime;
_duration = 0f;
_entities.Clear();
_bodies.Clear();
_instanceIdToEntityId.Clear();
_frames.Clear();
_events.Clear();
// Keep log + replay siblings: Logs/{matchId}.txt and Logs/{matchId}.json
if (_isPractice)
Logger.SetFileName(_matchId.ToString());
BuildEntities(gm);
string mode = _isPractice ? "practice" : "match";
Logger.Log($"ReplayRecorder started ({mode}) id {_matchId} with {_entities.Count} entities");
}
/// <summary>Negative unix timestamp so practice ids never collide with positive matchmaker ids.</summary>
static int GeneratePracticeMatchId()
{
long unix = DateTimeOffset.UtcNow.ToUnixTimeSeconds();
if (unix > int.MaxValue)
unix %= int.MaxValue;
int id = -(int)unix;
return id == 0 ? -1 : id;
}
void BuildEntities(GameManager gm)
{
if (gm.ball != null)
{
RegisterEntity(gm.ball.gameObject, gm.ball, "ball", "");
}
var sorted = new List<Puck>(gm.pucks);
sorted.Sort((a, b) =>
{
int teamCmp = a.team.CompareTo(b.team);
if (teamCmp != 0)
return teamCmp;
int xCmp = a.transform.position.x.CompareTo(b.transform.position.x);
if (xCmp != 0)
return xCmp;
return a.transform.position.y.CompareTo(b.transform.position.y);
});
foreach (Puck puck in sorted)
{
if (puck == null || puck.rb == null)
continue;
RegisterEntity(puck.gameObject, puck.rb, "puck", puck.team.ToString());
}
}
void RegisterEntity(GameObject go, Rigidbody2D rb, string type, string team)
{
int id = _entities.Count;
_entities.Add(new ReplayEntity { id = id, type = type, team = team ?? "" });
_bodies.Add(rb);
_instanceIdToEntityId[go.GetInstanceID()] = id;
}
float CurrentT() => Time.fixedTime - _startFixedTime;
void FixedUpdate()
{
if (!_recording || _flushed || !NetworkServer.active)
return;
int n = _bodies.Count;
if (n == 0)
return;
var frame = new ReplayFrame
{
t = CurrentT(),
x = new float[n],
y = new float[n],
vx = new float[n],
vy = new float[n]
};
for (int i = 0; i < n; i++)
{
Rigidbody2D rb = _bodies[i];
if (rb == null)
continue;
Vector2 pos = rb.position;
Vector2 vel = rb.linearVelocity;
frame.x[i] = pos.x;
frame.y[i] = pos.y;
frame.vx[i] = vel.x;
frame.vy[i] = vel.y;
}
_duration = frame.t;
_frames.Add(frame);
}
void AddHit(string kind, float vol, Component source)
{
int entityId = -1;
if (source != null)
_instanceIdToEntityId.TryGetValue(source.gameObject.GetInstanceID(), out entityId);
AddEvent(new ReplayEvent
{
t = CurrentT(),
type = "hit",
kind = kind ?? "",
vol = vol,
id = entityId,
team = "",
redScore = 0,
blueScore = 0,
kickoff = false
});
}
void AddEvent(ReplayEvent ev)
{
_events.Add(ev);
}
void Flush()
{
if (!_recording || _flushed)
return;
_flushed = true;
_recording = false;
_duration = Mathf.Max(_duration, CurrentT());
var file = new ReplayFile
{
version = 1,
matchId = _matchId,
isPractice = _isPractice,
fixedDeltaTime = Time.fixedDeltaTime,
duration = _duration,
entities = _entities.ToArray(),
frames = _frames.ToArray(),
events = _events.ToArray()
};
try
{
string path = ResolveReplayFilePath();
string json = JsonUtility.ToJson(file);
File.WriteAllText(path, json);
Logger.Log($"ReplayRecorder wrote {path} ({_frames.Count} frames, {_events.Count} events, duration {_duration:F2}s)");
}
catch (Exception e)
{
Logger.Log("ReplayRecorder flush failed: " + e.Message);
}
}
/// <summary>
/// Same directory and basename as the match log, extension <c>.json</c>
/// (e.g. <c>Logs/228.txt</c> → <c>Logs/228.json</c>).
/// </summary>
string ResolveReplayFilePath()
{
string expectedName = _matchId.ToString();
string logPath = Logger.instance != null ? Logger.instance.LogFilePath : null;
if (!string.IsNullOrEmpty(logPath))
{
string logBase = Path.GetFileNameWithoutExtension(logPath);
if (logBase == expectedName)
return Path.ChangeExtension(logPath, ".json");
}
return Path.Combine(Logger.GetLogsDirectory(), expectedName + ".json");
}
void OnDestroy()
{
if (Instance == this)
{
Flush();
Instance = null;
}
}
}
@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: c3d4e5f60718293a4b5c6d7e8f901a2b
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
+23 -1
View File
@@ -31,6 +31,11 @@ public class TutorialManagerMainMenu : MonoBehaviour
[Header("Screen 6")] [Header("Screen 6")]
public GameObject screen6; public GameObject screen6;
public Button btnNext6;
public CardCarousel gameModeCarousel;
[Header("Screen 7")]
public GameObject screen7;
public Button btnFinish; public Button btnFinish;
void Start() void Start()
@@ -38,8 +43,9 @@ public class TutorialManagerMainMenu : MonoBehaviour
btnNext1.onClick.AddListener(OnNext1); btnNext1.onClick.AddListener(OnNext1);
btnSkip.onClick.AddListener(OnSkip); btnSkip.onClick.AddListener(OnSkip);
btnNext2.onClick.AddListener(OnNext2); btnNext2.onClick.AddListener(OnNext2);
btnNext6.onClick.AddListener(OnNext6);
btnFinish.onClick.AddListener(OnTutorialCompleted); btnFinish.onClick.AddListener(OnStartTutorialMatch);
if(!forceShow){ if(!forceShow){
if(PlayerPrefs.HasKey(TUTORIAL_PREF_KEY)){ if(PlayerPrefs.HasKey(TUTORIAL_PREF_KEY)){
@@ -77,6 +83,15 @@ public class TutorialManagerMainMenu : MonoBehaviour
curScreen = 3; curScreen = 3;
} }
void OnNext6(){
screen6.SetActive(false);
screen7.SetActive(true);
gameModeCarousel.SetSelectedIndex(1);
curScreen = 7;
}
void OnNext3(){ void OnNext3(){
screen3.SetActive(false); screen3.SetActive(false);
screen4.SetActive(true); screen4.SetActive(true);
@@ -103,6 +118,13 @@ public class TutorialManagerMainMenu : MonoBehaviour
tutorialPanel.SetActive(false); tutorialPanel.SetActive(false);
} }
void OnStartTutorialMatch()
{
OnTutorialCompleted();
if (MainMenuManager.instance != null)
MainMenuManager.instance.OnPlayTutorial();
}
void Update() void Update()
{ {
if(curScreen < 2){return;} if(curScreen < 2){return;}
@@ -4,6 +4,7 @@ using DG.Tweening;
using UnityEngine.SceneManagement; using UnityEngine.SceneManagement;
using System.Collections; using System.Collections;
using TMPro; using TMPro;
using Mirror;
public class LevelLoadManager : MonoBehaviour public class LevelLoadManager : MonoBehaviour
{ {
public static LevelLoadManager instance; public static LevelLoadManager instance;
@@ -87,6 +88,7 @@ public class LevelLoadManager : MonoBehaviour
public void Show(){ public void Show(){
if(isShowing){return;} //already is showing
canvasGroup.blocksRaycasts=true; canvasGroup.blocksRaycasts=true;
canvasGroup.interactable=true; canvasGroup.interactable=true;
contentImage.fillOrigin = 0; contentImage.fillOrigin = 0;
@@ -180,4 +182,26 @@ public class LevelLoadManager : MonoBehaviour
p2_l10.text = $"L10 {opponentPlayer.l10_wins}-{opponentPlayer.l10_losses}"; p2_l10.text = $"L10 {opponentPlayer.l10_wins}-{opponentPlayer.l10_losses}";
} }
public void Leave(string levelName = "MainMenu"){
NetManager.StopNetworkingForSceneChange();
StartCoroutine(CoroutineWaitTillDisconnection(levelName));
}
IEnumerator CoroutineWaitTillDisconnection(string levelName){
Show(); //Load the UI until the level is loaded
const float timeoutSeconds = 5f;
float elapsed = 0f;
while ((NetworkClient.isConnected || NetworkClient.active || NetworkServer.active) && elapsed < timeoutSeconds)
{
elapsed += Time.unscaledDeltaTime;
yield return null;
}
yield return new WaitForSeconds(0.25f);
LoadLevel(levelName);
}
} }
+1
View File
@@ -6,6 +6,7 @@ public class UserData
{ {
public int id; public int id;
public string username; public string username;
public string email;
public int cc; public int cc;
public int rc; public int rc;
public string created_at; public string created_at;
@@ -0,0 +1,10 @@
using System;
using UnityEngine;
[Serializable]
public class PingReportApiResponse
{
public bool ok;
public string error;
public PingReportData report;
}
@@ -0,0 +1,2 @@
fileFormatVersion: 2
guid: 76e4e69960816204d8a01d0e534e0bf4
@@ -0,0 +1,13 @@
using System;
using UnityEngine;
[Serializable]
public class PingReportData
{
public int id;
public int user_id;
public int match_id;
public int ping;
public string ip_address;
public string created_at;
}
@@ -0,0 +1,2 @@
fileFormatVersion: 2
guid: b3f6089d3b18cb34482d7de0cd8bca51
+456
View File
@@ -0,0 +1,456 @@
using System;
using System.Collections.Generic;
using DG.Tweening;
using UnityEngine;
using UnityEngine.Events;
using UnityEngine.EventSystems;
using UnityEngine.UI;
[RequireComponent(typeof(EventTrigger))]
public class CardCarousel : MonoBehaviour
{
[SerializeField] RectTransform[] items;
[SerializeField] float spacing = 40f;
[SerializeField] float swipeThreshold = 60f;
[SerializeField] float snapDuration = 0.25f;
[SerializeField] Ease snapEase = Ease.OutCubic;
[Tooltip("Horizontal half-width of the center tap zone, in local units of this RectTransform.")]
[SerializeField] float centerTapHalfWidth = 260f;
[SerializeField] bool looped = true;
[SerializeField] int selectedIndex;
[Header("Focus Animation")]
[SerializeField] float activeScale = 1.05f;
[SerializeField] float inactiveScale = 0.88f;
[SerializeField] float activePullDown = 35f;
public UnityEvent<int> onSelected = new UnityEvent<int>();
EventTrigger eventTrigger;
RectTransform rectTransform;
RectTransform dragSpace;
RectTransform duplicateClone;
readonly Dictionary<RectTransform, Vector3> baseScales = new();
float slotStep;
float focusX;
float focusY;
float focusPosition;
float dragStartPosition;
float pointerDownLocalX;
bool isDragging;
bool isAnimating;
Tween snapTween;
public int SelectedIndex => selectedIndex;
void Awake()
{
rectTransform = (RectTransform)transform;
eventTrigger = GetComponent<EventTrigger>();
RegisterTrigger(EventTriggerType.PointerDown, OnPointerDown);
RegisterTrigger(EventTriggerType.Drag, OnDrag);
RegisterTrigger(EventTriggerType.PointerUp, OnPointerUp);
}
void Start()
{
if (items == null || items.Length < 2)
{
Debug.LogWarning($"{nameof(CardCarousel)} on {name} needs at least 2 items.", this);
return;
}
selectedIndex = Mathf.Clamp(selectedIndex, 0, items.Length - 1);
dragSpace = items[0].parent as RectTransform;
slotStep = items[0].rect.width + spacing;
focusX = items[0].anchoredPosition.x;
focusY = items[0].anchoredPosition.y;
duplicateClone = CreateClone(items[0], "_carouselClone_Dup");
foreach (var item in items)
CacheBaseScale(item);
focusPosition = selectedIndex;
ApplyLayout();
}
void OnDestroy()
{
snapTween?.Kill();
}
void RegisterTrigger(EventTriggerType type, Action<BaseEventData> handler)
{
var entry = new EventTrigger.Entry { eventID = type };
entry.callback.AddListener(handler.Invoke);
eventTrigger.triggers.Add(entry);
}
RectTransform CreateClone(RectTransform source, string suffix)
{
var clone = Instantiate(source, source.parent);
clone.name = source.name + suffix;
DisableInteractions(clone);
return clone;
}
static void DisableInteractions(RectTransform target)
{
foreach (var graphic in target.GetComponentsInChildren<Graphic>(true))
graphic.raycastTarget = false;
foreach (var button in target.GetComponentsInChildren<Button>(true))
button.interactable = false;
}
void OnPointerDown(BaseEventData eventData)
{
if (!TryGetPointer(eventData, out var pointer) || isAnimating || items == null || items.Length < 2)
return;
snapTween?.Kill();
isAnimating = false;
isDragging = false;
dragStartPosition = focusPosition;
pointerDownLocalX = GetLocalDragX(pointer);
}
void OnDrag(BaseEventData eventData)
{
if (!TryGetPointer(eventData, out var pointer) || items == null || items.Length < 2)
return;
isDragging = true;
float delta = GetLocalDragX(pointer) - pointerDownLocalX;
focusPosition = dragStartPosition - delta / slotStep;
if (!looped)
focusPosition = Mathf.Clamp(focusPosition, 0f, items.Length - 1);
ApplyLayout();
}
void OnPointerUp(BaseEventData eventData)
{
if (!TryGetPointer(eventData, out var pointer) || isAnimating || items == null || items.Length < 2)
return;
float pointerDelta = GetLocalDragX(pointer) - pointerDownLocalX;
float dragDelta = focusPosition - dragStartPosition;
bool passedSwipeThreshold = Mathf.Abs(pointerDelta) >= swipeThreshold
|| Mathf.Abs(dragDelta * slotStep) >= swipeThreshold;
if (!passedSwipeThreshold)
{
if (TryGetTapZone(pointer, out int tapDirection))
{
if (tapDirection == 0)
SelectCurrent();
else if (CanMoveBy(tapDirection))
AnimateToDirection(tapDirection);
else
SnapTo(selectedIndex, null);
}
else
SnapTo(selectedIndex, null);
isDragging = false;
return;
}
isDragging = false;
int direction = dragDelta > 0f ? 1 : -1;
if (Mathf.Abs(focusPosition - selectedIndex) > 0.5f)
{
int nearest = Mathf.RoundToInt(focusPosition);
if (!looped)
nearest = Mathf.Clamp(nearest, 0, items.Length - 1);
if (nearest != selectedIndex && CanMoveBy(nearest > selectedIndex ? 1 : -1))
{
AnimateTo(nearest);
return;
}
}
if (!CanMoveBy(direction))
{
SnapTo(selectedIndex, null);
return;
}
AnimateToDirection(direction);
}
float GetLocalDragX(PointerEventData pointer)
{
if (dragSpace == null)
return pointer.position.x;
RectTransformUtility.ScreenPointToLocalPointInRectangle(
dragSpace, pointer.position, pointer.pressEventCamera, out var local);
return local.x;
}
bool TryGetTapZone(PointerEventData pointer, out int direction)
{
direction = 0;
if (!RectTransformUtility.ScreenPointToLocalPointInRectangle(
rectTransform, pointer.position, pointer.pressEventCamera, out var local))
return false;
if (Mathf.Abs(local.x) <= centerTapHalfWidth)
return true;
direction = local.x < 0f ? -1 : 1;
return true;
}
void SelectCurrent()
{
if (Mathf.Approximately(focusPosition, selectedIndex))
onSelected.Invoke(selectedIndex);
else
SnapTo(selectedIndex, () => onSelected.Invoke(selectedIndex));
}
void AnimateToDirection(int direction)
{
int newIndex = GetAdjacentIndex(direction, items.Length);
if (newIndex < 0)
return;
AnimateTo(newIndex);
}
void AnimateTo(int newIndex)
{
isAnimating = true;
snapTween?.Kill();
snapTween = DOTween.To(
() => focusPosition,
value =>
{
focusPosition = value;
ApplyLayout();
},
newIndex,
snapDuration)
.SetEase(snapEase)
.OnComplete(() => CompleteSlide(newIndex));
}
void CompleteSlide(int newIndex)
{
selectedIndex = newIndex;
focusPosition = newIndex;
isAnimating = false;
ApplyLayout();
}
void SnapTo(float targetPosition, Action onComplete)
{
isAnimating = true;
snapTween?.Kill();
snapTween = DOTween.To(
() => focusPosition,
value =>
{
focusPosition = value;
ApplyLayout();
},
targetPosition,
snapDuration)
.SetEase(snapEase)
.OnComplete(() =>
{
isAnimating = false;
onComplete?.Invoke();
});
}
float GetItemOffset(int itemIndex)
{
return (itemIndex - focusPosition) * slotStep;
}
bool IsItemVisible(float offset)
{
return Mathf.Abs(offset) <= slotStep * 1.5f;
}
void ApplyLayout()
{
int count = items.Length;
bool useDuplicate = looped && count == 2;
for (int i = 0; i < count; i++)
{
float offset = GetItemOffset(i);
if (IsItemVisible(offset))
{
SetItemTransform(items[i], offset);
items[i].gameObject.SetActive(true);
}
else
items[i].gameObject.SetActive(false);
}
if (useDuplicate && Mathf.Approximately(focusPosition, Mathf.Round(focusPosition)))
{
int restIndex = Mathf.RoundToInt(focusPosition);
int otherIndex = 1 - restIndex;
float otherOffset = GetItemOffset(otherIndex);
float duplicateOffset = -otherOffset;
if (IsItemVisible(duplicateOffset))
{
SyncDuplicateClone(items[otherIndex]);
SetItemTransform(duplicateClone, duplicateOffset);
duplicateClone.gameObject.SetActive(true);
}
else if (duplicateClone != null)
duplicateClone.gameObject.SetActive(false);
}
else if (duplicateClone != null)
{
duplicateClone.gameObject.SetActive(false);
}
int topIndex = 0;
float bestFocus = float.MaxValue;
for (int i = 0; i < count; i++)
{
if (!items[i].gameObject.activeSelf)
continue;
float focus = GetFocusT(GetItemOffset(i));
if (focus < bestFocus)
{
bestFocus = focus;
topIndex = i;
}
}
items[topIndex].SetAsLastSibling();
}
void SyncDuplicateClone(RectTransform source)
{
string expectedName = source.name + "_carouselClone_Dup";
if (duplicateClone == null || duplicateClone.name != expectedName)
{
var parent = source.parent;
int sibling = duplicateClone != null ? duplicateClone.GetSiblingIndex() : source.GetSiblingIndex();
if (duplicateClone != null)
{
baseScales.Remove(duplicateClone);
Destroy(duplicateClone.gameObject);
}
duplicateClone = CreateClone(source, "_carouselClone_Dup");
duplicateClone.SetParent(parent, false);
duplicateClone.SetSiblingIndex(sibling);
}
CacheBaseScale(duplicateClone, source);
}
void CacheBaseScale(RectTransform item, RectTransform source = null)
{
if (baseScales.ContainsKey(item))
return;
baseScales[item] = source != null ? source.localScale : item.localScale;
}
void SetItemTransform(RectTransform item, float xOffset)
{
CacheBaseScale(item);
float focusT = GetFocusT(xOffset);
float scale = Mathf.Lerp(activeScale, inactiveScale, focusT);
item.localScale = baseScales[item] * scale;
var pos = item.anchoredPosition;
pos.x = focusX + xOffset;
pos.y = focusY - Mathf.Lerp(activePullDown, 0f, focusT);
item.anchoredPosition = pos;
}
float GetFocusT(float xOffset)
{
if (slotStep <= 0f)
return 0f;
float t = Mathf.Clamp01(Mathf.Abs(xOffset) / slotStep);
return t * t * (3f - 2f * t);
}
static int WrapIndex(int index, int count)
{
if (count <= 0)
return 0;
return ((index % count) + count) % count;
}
int GetAdjacentIndex(int direction, int count)
{
int index = selectedIndex + direction;
if (looped)
return WrapIndex(index, count);
return index >= 0 && index < count ? index : -1;
}
bool CanMoveBy(int direction)
{
if (items == null || items.Length == 0)
return false;
return GetAdjacentIndex(direction, items.Length) >= 0;
}
int NormalizeIndex(int index)
{
if (items == null || items.Length == 0)
return 0;
return looped ? WrapIndex(index, items.Length) : Mathf.Clamp(index, 0, items.Length - 1);
}
static bool TryGetPointer(BaseEventData eventData, out PointerEventData pointer)
{
pointer = eventData as PointerEventData;
return pointer != null;
}
public void SetSelectedIndex(int index, bool animate = false)
{
if (items == null || items.Length == 0)
return;
int target = NormalizeIndex(index);
if (target == selectedIndex)
return;
if (!animate || !isActiveAndEnabled)
{
snapTween?.Kill();
isAnimating = false;
selectedIndex = target;
focusPosition = target;
ApplyLayout();
return;
}
int direction = target > selectedIndex ? 1 : -1;
if (!CanMoveBy(direction) || Mathf.Abs(target - selectedIndex) != 1)
{
selectedIndex = target;
focusPosition = target;
ApplyLayout();
return;
}
AnimateToDirection(direction);
}
}
@@ -0,0 +1,2 @@
fileFormatVersion: 2
guid: a4951ec6b41c5d14cb8f5a8803dfa0c2
+17 -15
View File
@@ -3,9 +3,9 @@ using UnityEngine.Rendering;
using UnityEngine.UI; using UnityEngine.UI;
/// <summary> /// <summary>
/// Inverted stencil mask (see materialForRendering). For raycasts, assign /// Inverted stencil mask (see materialForRendering). Raycast options live on
/// <see cref="raycastPassThroughRects"/> to rects that match each visual "hole" /// <see cref="CutoutMaskUISettings"/> on the same GameObject (Unity's Image
/// — clicks there wont hit this graphic and pass to UI behind. /// inspector does not show fields on Image subclasses).
/// ///
/// Parent <see cref="Mask"/> also implements <see cref="ICanvasRaycastFilter"/> and only /// Parent <see cref="Mask"/> also implements <see cref="ICanvasRaycastFilter"/> and only
/// allows points inside its RectTransform. A fullscreen child under a small mask would /// allows points inside its RectTransform. A fullscreen child under a small mask would
@@ -15,13 +15,10 @@ using UnityEngine.UI;
/// ignoreMasks) so hit testing matches the fullscreen Image; rendering still uses stencil /// ignoreMasks) so hit testing matches the fullscreen Image; rendering still uses stencil
/// because <see cref="MaskableGraphic.maskable"/> stays true. /// because <see cref="MaskableGraphic.maskable"/> stays true.
/// </summary> /// </summary>
[RequireComponent(typeof(CutoutMaskUISettings))]
public class CutoutMaskUI : Image public class CutoutMaskUI : Image
{ {
[Tooltip("Rects matching cutout/hole areas. Clicks inside are not consumed by this Image. Leave empty to use the parent Masks RectTransform.")] CutoutMaskUISettings settings;
[SerializeField] RectTransform[] raycastPassThroughRects;
[Tooltip("The Image on the same object as Mask is usually the cutout shape and still receives raycasts. When this is on, that graphics Raycast Target is turned off while this component is enabled so the hole reaches UI behind the overlay.")]
[SerializeField] bool disableRaycastOnParentMaskGraphic = true;
Mask cachedParentMask; Mask cachedParentMask;
Graphic cachedMaskGraphic; Graphic cachedMaskGraphic;
@@ -33,8 +30,10 @@ public class CutoutMaskUI : Image
return Raycast(sp, eventCamera, ignoreMasks: true); return Raycast(sp, eventCamera, ignoreMasks: true);
} }
public override Material materialForRendering{ public override Material materialForRendering
get{ {
get
{
Material material = new Material(base.materialForRendering); Material material = new Material(base.materialForRendering);
material.SetInt("_StencilComp", (int)CompareFunction.NotEqual); material.SetInt("_StencilComp", (int)CompareFunction.NotEqual);
return material; return material;
@@ -43,8 +42,10 @@ public class CutoutMaskUI : Image
protected override void OnEnable() protected override void OnEnable()
{ {
settings = GetComponent<CutoutMaskUISettings>();
base.OnEnable(); base.OnEnable();
if (!disableRaycastOnParentMaskGraphic)
if (settings == null || !settings.disableRaycastOnParentMaskGraphic)
return; return;
cachedParentMask = GetComponentInParent<Mask>(); cachedParentMask = GetComponentInParent<Mask>();
@@ -76,18 +77,19 @@ public class CutoutMaskUI : Image
public override bool IsRaycastLocationValid(Vector2 screenPoint, Camera eventCamera) public override bool IsRaycastLocationValid(Vector2 screenPoint, Camera eventCamera)
{ {
if (IsInsidePassThroughHole(screenPoint, eventCamera)) if (IsInsidePassThroughHole(screenPoint, eventCamera))
return false; return settings != null && settings.blockRaycastThroughCutout;
return base.IsRaycastLocationValid(screenPoint, eventCamera); return base.IsRaycastLocationValid(screenPoint, eventCamera);
} }
bool IsInsidePassThroughHole(Vector2 screenPoint, Camera eventCamera) bool IsInsidePassThroughHole(Vector2 screenPoint, Camera eventCamera)
{ {
if (raycastPassThroughRects != null) RectTransform[] passThroughRects = settings != null ? settings.raycastPassThroughRects : null;
if (passThroughRects != null)
{ {
for (int i = 0; i < raycastPassThroughRects.Length; i++) for (int i = 0; i < passThroughRects.Length; i++)
{ {
RectTransform rect = raycastPassThroughRects[i]; RectTransform rect = passThroughRects[i];
if (rect != null && RectTransformUtility.RectangleContainsScreenPoint(rect, screenPoint, eventCamera)) if (rect != null && RectTransformUtility.RectangleContainsScreenPoint(rect, screenPoint, eventCamera))
return true; return true;
} }
@@ -0,0 +1,15 @@
using UnityEngine;
[DisallowMultipleComponent]
[RequireComponent(typeof(CutoutMaskUI))]
public class CutoutMaskUISettings : MonoBehaviour
{
[Tooltip("Rects matching cutout/hole areas. Clicks inside are not consumed by this Image. Leave empty to use the parent Mask's RectTransform.")]
public RectTransform[] raycastPassThroughRects;
[Tooltip("The Image on the same object as Mask is usually the cutout shape and still receives raycasts. When this is on, that graphic's Raycast Target is turned off while this component is enabled so the hole reaches UI behind the overlay.")]
public bool disableRaycastOnParentMaskGraphic = true;
[Tooltip("When enabled, clicks inside cutout/hole areas are consumed by this Image instead of passing through to UI behind.")]
public bool blockRaycastThroughCutout;
}
@@ -0,0 +1,2 @@
fileFormatVersion: 2
guid: 29b95265513fc314995c59cb90745214
+8
View File
@@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 05aa9e67ef3520047a8c20a6f96165d8
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:
+64 -13
View File
@@ -19,6 +19,7 @@ public class FrameAnimator : MonoBehaviour
bool m_previewPlaying = false; bool m_previewPlaying = false;
#if UNITY_EDITOR #if UNITY_EDITOR
double m_lastEditorTime = 0d; double m_lastEditorTime = 0d;
bool m_editorHooked;
#endif #endif
Image m_img; Image m_img;
Image img { Image img {
@@ -42,19 +43,19 @@ public class FrameAnimator : MonoBehaviour
void OnEnable() void OnEnable()
{ {
#if UNITY_EDITOR #if UNITY_EDITOR
if (!Application.isPlaying) // Never hook editor updates during play-mode enter/exit — QueuePlayerLoopUpdate
{ // + isPlaying serialized true can infinite-reload Temp/__Backupscenes.
m_lastEditorTime = EditorApplication.timeSinceStartup; EditorApplication.playModeStateChanged -= OnPlayModeStateChanged;
EditorApplication.update -= OnEditorUpdate; EditorApplication.playModeStateChanged += OnPlayModeStateChanged;
EditorApplication.update += OnEditorUpdate; TryHookEditorUpdate();
}
#endif #endif
} }
void OnDisable() void OnDisable()
{ {
#if UNITY_EDITOR #if UNITY_EDITOR
EditorApplication.update -= OnEditorUpdate; UnhookEditorUpdate();
EditorApplication.playModeStateChanged -= OnPlayModeStateChanged;
#endif #endif
} }
void Start() void Start()
@@ -80,24 +81,72 @@ public class FrameAnimator : MonoBehaviour
} }
#if UNITY_EDITOR #if UNITY_EDITOR
void OnEditorUpdate() void OnPlayModeStateChanged(PlayModeStateChange state)
{ {
if (Application.isPlaying || this == null || !isActiveAndEnabled) if (state == PlayModeStateChange.ExitingEditMode ||
state == PlayModeStateChange.EnteredPlayMode ||
state == PlayModeStateChange.ExitingPlayMode)
{ {
m_previewPlaying = false;
UnhookEditorUpdate();
}
else if (state == PlayModeStateChange.EnteredEditMode)
{
TryHookEditorUpdate();
}
}
void TryHookEditorUpdate()
{
if (Application.isPlaying || EditorApplication.isPlayingOrWillChangePlaymode)
{
UnhookEditorUpdate();
return; return;
} }
if (m_editorHooked)
return;
m_lastEditorTime = EditorApplication.timeSinceStartup;
EditorApplication.update += OnEditorUpdate;
m_editorHooked = true;
}
void UnhookEditorUpdate()
{
if (!m_editorHooked)
return;
EditorApplication.update -= OnEditorUpdate;
m_editorHooked = false;
}
void OnEditorUpdate()
{
if (Application.isPlaying ||
EditorApplication.isPlayingOrWillChangePlaymode ||
this == null ||
!isActiveAndEnabled)
{
UnhookEditorUpdate();
return;
}
// Edit-mode animation is preview-only. Ignoring serialized isPlaying prevents
// permanent editor loops when isPlaying was left true in the scene.
if (!m_previewPlaying)
return;
double now = EditorApplication.timeSinceStartup; double now = EditorApplication.timeSinceStartup;
float dt = (float)(now - m_lastEditorTime); float dt = (float)(now - m_lastEditorTime);
m_lastEditorTime = now; m_lastEditorTime = now;
if (dt <= 0f) if (dt <= 0f)
{
return; return;
}
int frameBefore = currentFrame;
TickAnimation(dt); TickAnimation(dt);
EditorApplication.QueuePlayerLoopUpdate(); if (currentFrame != frameBefore || m_previewPlaying)
EditorApplication.QueuePlayerLoopUpdate();
} }
#endif #endif
@@ -108,7 +157,9 @@ public class FrameAnimator : MonoBehaviour
return; return;
} }
bool shouldAnimate = m_previewPlaying || isPlaying; bool shouldAnimate = Application.isPlaying
? (m_previewPlaying || isPlaying)
: m_previewPlaying;
if (!shouldAnimate) if (!shouldAnimate)
{ {
return; return;
@@ -10,7 +10,7 @@ MonoBehaviour:
m_Enabled: 1 m_Enabled: 1
m_EditorHideFlags: 0 m_EditorHideFlags: 0
m_Script: {fileID: 15003, guid: 0000000000000000e000000000000000, type: 0} m_Script: {fileID: 15003, guid: 0000000000000000e000000000000000, type: 0}
m_Name: "New Android\u2122 Profile" m_Name: Android
m_EditorClassIdentifier: m_EditorClassIdentifier:
m_AssetVersion: 1 m_AssetVersion: 1
m_BuildTarget: 13 m_BuildTarget: 13
@@ -23,7 +23,7 @@ MonoBehaviour:
- m_enabled: 1 - m_enabled: 1
m_path: Assets/Scenes/MainMenu.unity m_path: Assets/Scenes/MainMenu.unity
- m_enabled: 1 - m_enabled: 1
m_path: Assets/Scenes/Proto.unity m_path: Assets/Scenes/Game.unity
m_ScriptingDefines: [] m_ScriptingDefines: []
m_PlayerSettingsYaml: m_PlayerSettingsYaml:
m_Settings: m_Settings:
@@ -10,7 +10,7 @@ MonoBehaviour:
m_Enabled: 1 m_Enabled: 1
m_EditorHideFlags: 0 m_EditorHideFlags: 0
m_Script: {fileID: 15003, guid: 0000000000000000e000000000000000, type: 0} m_Script: {fileID: 15003, guid: 0000000000000000e000000000000000, type: 0}
m_Name: New Linux Server Profile 1 m_Name: Server
m_EditorClassIdentifier: m_EditorClassIdentifier:
m_AssetVersion: 1 m_AssetVersion: 1
m_BuildTarget: 24 m_BuildTarget: 24
+8
View File
@@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 6ed105eb05a66ba478d06322acc25c79
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:
+8
View File
@@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: da48e3104d59dfc43987d0df0c3a6df3
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:
@@ -0,0 +1,72 @@
%YAML 1.1
%TAG !u! tag:unity3d.com,2011:
--- !u!1107 &-8584330192966582573
AnimatorStateMachine:
serializedVersion: 6
m_ObjectHideFlags: 1
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_Name: Base Layer
m_ChildStates:
- serializedVersion: 1
m_State: {fileID: -6079159438373275284}
m_Position: {x: 200, y: 0, z: 0}
m_ChildStateMachines: []
m_AnyStateTransitions: []
m_EntryTransitions: []
m_StateMachineTransitions: {}
m_StateMachineBehaviours: []
m_AnyStatePosition: {x: 50, y: 20, z: 0}
m_EntryPosition: {x: 50, y: 120, z: 0}
m_ExitPosition: {x: 800, y: 120, z: 0}
m_ParentStateMachinePosition: {x: 800, y: 20, z: 0}
m_DefaultState: {fileID: -6079159438373275284}
--- !u!1102 &-6079159438373275284
AnimatorState:
serializedVersion: 6
m_ObjectHideFlags: 1
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_Name: goal
m_Speed: 1
m_CycleOffset: 0
m_Transitions: []
m_StateMachineBehaviours: []
m_Position: {x: 50, y: 50, z: 0}
m_IKOnFeet: 0
m_WriteDefaultValues: 1
m_Mirror: 0
m_SpeedParameterActive: 0
m_MirrorParameterActive: 0
m_CycleOffsetParameterActive: 0
m_TimeParameterActive: 0
m_Motion: {fileID: 7400000, guid: 012b635d069efe04eb565eb2f83ff075, type: 2}
m_Tag:
m_SpeedParameter:
m_MirrorParameter:
m_CycleOffsetParameter:
m_TimeParameter:
--- !u!91 &9100000
AnimatorController:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_Name: Goal
serializedVersion: 5
m_AnimatorParameters: []
m_AnimatorLayers:
- serializedVersion: 5
m_Name: Base Layer
m_StateMachine: {fileID: -8584330192966582573}
m_Mask: {fileID: 0}
m_Motions: []
m_Behaviours: []
m_BlendingMode: 0
m_SyncedLayerIndex: -1
m_DefaultWeight: 0
m_IKPass: 0
m_SyncedLayerAffectsTiming: 0
m_Controller: {fileID: 9100000}
@@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: c66c766fdc763724190ee6e7bac71f4f
NativeFormatImporter:
externalObjects: {}
mainObjectFileID: 9100000
userData:
assetBundleName:
assetBundleVariant:
@@ -0,0 +1,405 @@
%YAML 1.1
%TAG !u! tag:unity3d.com,2011:
--- !u!74 &7400000
AnimationClip:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_Name: goal
serializedVersion: 7
m_Legacy: 0
m_Compressed: 0
m_UseHighQualityCurve: 1
m_RotationCurves: []
m_CompressedRotationCurves: []
m_EulerCurves: []
m_PositionCurves: []
m_ScaleCurves: []
m_FloatCurves: []
m_PPtrCurves:
- serializedVersion: 2
curve:
- time: 0
value: {fileID: 2326327491318180270, guid: b6c56c1425fa2f8408c994c527e26a90, type: 3}
- time: 0.033333335
value: {fileID: 3039656268719684704, guid: 57ade1617fe03ce47973f453d69b3480, type: 3}
- time: 0.05
value: {fileID: -9148344310071500359, guid: 5856e0a6a3e22894db0495cb4f47090b, type: 3}
- time: 0.083333336
value: {fileID: -8946820737381054217, guid: c1ed0abc4be1a814089f41698b1a6ae9, type: 3}
- time: 0.1
value: {fileID: 1169171792133349783, guid: d661c41bdd54f0749a3f6ce9b76922b9, type: 3}
- time: 0.13333334
value: {fileID: -9162835414837137971, guid: 1e52d3e76a6ad9240b43596c128083c2, type: 3}
- time: 0.16666667
value: {fileID: 4054532105436495736, guid: ffdf322806b69f14184628cb835d4651, type: 3}
- time: 0.18333334
value: {fileID: -2769560261860674534, guid: bf96e93cb75a36b4d9e7bd6be37c49c1, type: 3}
- time: 0.21666667
value: {fileID: 337469173700556176, guid: 0380b9106f20e364f9829e45849b93b5, type: 3}
- time: 0.25
value: {fileID: -1893092822091598629, guid: 2889f9b33b3507d4596f7460716eb88a, type: 3}
- time: 0.26666668
value: {fileID: -3779762386179194896, guid: dd8d5e7fd43d915419a9bc4c4a13c87f, type: 3}
- time: 0.3
value: {fileID: 1568047047368444430, guid: 58f8fdb8db035fe42925165db312de6f, type: 3}
- time: 0.31666666
value: {fileID: 3341768276131303601, guid: 571163594414f9940a46e54e3a28ba3e, type: 3}
- time: 0.35
value: {fileID: -3274699238553858469, guid: c3ea11aecfb35934fbd6ebfd75367b7f, type: 3}
- time: 0.38333333
value: {fileID: -2904124417626424539, guid: cbb0ccfaf845bcf4b9b318e7e17b2386, type: 3}
- time: 0.4
value: {fileID: 7807152604696158922, guid: 648f5791cf82b074eb22242756e7a84e, type: 3}
- time: 0.43333334
value: {fileID: -7436839558645834474, guid: ddc6d2f24c0fc464089d070137d69153, type: 3}
- time: 0.46666667
value: {fileID: 8094720510830227213, guid: c8cf7aae8cc60584989fd3e5780d9ada, type: 3}
- time: 0.48333332
value: {fileID: 7779922750506681629, guid: de8f5c49b9afd07468509051e66d2cdf, type: 3}
- time: 0.51666665
value: {fileID: 3496087471285781191, guid: 4e82a0023f2925e4095a945e6cdd7561, type: 3}
- time: 0.53333336
value: {fileID: 8638417948329565305, guid: ea3ab7e6dc988d84d9f772ca6247306c, type: 3}
- time: 0.56666666
value: {fileID: -271827495750292581, guid: 6d2967a2a13b6bf4c944e5ba6deec0c9, type: 3}
- time: 0.6
value: {fileID: -3388446827607515280, guid: 3f05fc19723cfe348825f234e8f6dc95, type: 3}
- time: 0.6166667
value: {fileID: -1666824402963536844, guid: 8869e8a80c6427347885e0af01056060, type: 3}
- time: 0.65
value: {fileID: -8937177477147073390, guid: 23b9137b4ee9787419733f698cdf432a, type: 3}
- time: 0.68333334
value: {fileID: -8799646602856602245, guid: caa45998ad7697c439e4394aad15e4ce, type: 3}
- time: 0.7
value: {fileID: -2919293107161874442, guid: f6a7a1413dd7e574db87a9e167b55107, type: 3}
- time: 0.73333335
value: {fileID: -4394205086732167005, guid: cdbe41dacfeb21b44b800a49ea2b81fb, type: 3}
- time: 0.75
value: {fileID: 5667663509541448309, guid: c70f3e48526c5094a86cd4e39ba85b3e, type: 3}
- time: 0.78333336
value: {fileID: 7348336625229709678, guid: 189527c7e3a0a004db2872b0a8e3ceb5, type: 3}
- time: 0.81666666
value: {fileID: 5931598933246611655, guid: 6a5cac00dbe17394b801517dc895647d, type: 3}
- time: 0.8333333
value: {fileID: 8452745832453081500, guid: 280d3c25be2edeb4fa02d7dd04a03c9a, type: 3}
- time: 0.8666667
value: {fileID: -3621795988406732249, guid: f63b7fb53f154d74e8ec8146aca6048c, type: 3}
- time: 0.9
value: {fileID: 2240764819728979505, guid: 0e16df8ab797e6241ae23dd4e6ce487b, type: 3}
- time: 0.9166667
value: {fileID: 7879484713341989712, guid: 700fd15bd9288ed45b5714d9edc52b3b, type: 3}
- time: 0.95
value: {fileID: -9213452353189187973, guid: f1736e31cb0f483469813ba9b38b565f, type: 3}
- time: 0.96666664
value: {fileID: 2111467077804923315, guid: f88d784d9e7233e4c87665470234f383, type: 3}
- time: 1
value: {fileID: -874371296305861922, guid: 4353b503ea33bad4e8bd869ded3100b1, type: 3}
- time: 1.0333333
value: {fileID: -4722877178089714693, guid: d258334f319668a428336f65d585323d, type: 3}
- time: 1.05
value: {fileID: 974538412794390107, guid: 9129d4098d9b04447914c959d45da0f1, type: 3}
- time: 1.0833334
value: {fileID: 1355229876367979772, guid: 95a9226d51366fc4fa6eb18e2bafd39d, type: 3}
- time: 1.1
value: {fileID: 7670519301962771510, guid: 9f9a286b35209e143a2f188b2c11433d, type: 3}
- time: 1.1333333
value: {fileID: 6072851112962974044, guid: f7bce4982cec5fc468e902196fae045f, type: 3}
- time: 1.1666666
value: {fileID: -6319862089727399332, guid: be8eac887eec56f4297b6e510b403dcd, type: 3}
- time: 1.1833333
value: {fileID: -932602025479058729, guid: c4c5a559eb5006e47b1bd6e98976d9de, type: 3}
- time: 1.2166667
value: {fileID: -7645832949135137003, guid: d4c174fae4c6e0d4ca27a5f3b7730cae, type: 3}
- time: 1.25
value: {fileID: -2393745200414661269, guid: f2e36a58d1e243e49b88241ee20c4877, type: 3}
- time: 1.2666667
value: {fileID: 8977753790170574155, guid: ffe7d49e866535c4a958570317642a95, type: 3}
- time: 1.3
value: {fileID: 1589886341371401149, guid: 37bebf89626e0f448b58b969c93d40e0, type: 3}
- time: 1.3166667
value: {fileID: 1958469704995616933, guid: cb546a3527c851741b9212711d924a7b, type: 3}
- time: 1.35
value: {fileID: -1663287010409347934, guid: 76bbadb6b73973a41991e331f2a30d0b, type: 3}
- time: 1.3833333
value: {fileID: 8931199389144512364, guid: 2f95eff7070e49b429851d2b3caaef25, type: 3}
- time: 1.4
value: {fileID: -6375165851556118606, guid: f8882cd79155d3d40b015470c68b0e08, type: 3}
- time: 1.4333333
value: {fileID: 2605750455627557777, guid: fd8f39578bf065e4c91ebcf5573f9efe, type: 3}
- time: 1.4666667
value: {fileID: -7979054687685788317, guid: 9361603dbccdeec408a7b2c5e4ada410, type: 3}
- time: 1.4833333
value: {fileID: -7790389344213789306, guid: 8dd1b385ee834454198b2e1166eb79c8, type: 3}
- time: 1.5166667
value: {fileID: -8385755097310045752, guid: 5b2adc75c3720904d83e321082194705, type: 3}
- time: 1.5333333
value: {fileID: 5114680995901985376, guid: 936f75db652ba3745a81715cbc04f234, type: 3}
- time: 1.5666667
value: {fileID: 6219192158437786728, guid: e6bf6c1c3a65cab4288b8cc2fc87d781, type: 3}
- time: 1.6
value: {fileID: -8483101290065073045, guid: 460b39275c0556640a8ab23969fe9835, type: 3}
- time: 1.6166667
value: {fileID: -5795086960448516603, guid: c5d1f615ddbd6344ca8fb0d5117ac417, type: 3}
- time: 1.65
value: {fileID: -7690586406086400816, guid: 7401181cefca1f14b8efcf047d133d22, type: 3}
- time: 1.6833333
value: {fileID: 7994291799538021827, guid: 1fe673cd12f828e4cbc61380eae47dd6, type: 3}
- time: 1.7
value: {fileID: -4622645856484230464, guid: 94e4567f457e037408f3260d5900d576, type: 3}
- time: 1.7333333
value: {fileID: -7119226307677305272, guid: d59f1a8ea5a27d044be1a889967031cb, type: 3}
- time: 1.75
value: {fileID: -2510434210989532096, guid: 2a58d9c6fd7e10f43b009158bed30950, type: 3}
- time: 1.7833333
value: {fileID: -1900014500118246637, guid: 4efc235d4ede2274fb505615a66d05e0, type: 3}
- time: 1.8166667
value: {fileID: -5548813928269055359, guid: d30d839f35579f04eb735a7f0ce2714b, type: 3}
- time: 1.8333334
value: {fileID: -8779485291810269718, guid: 1cc644f034f91e04e9160a1bca22e24d, type: 3}
- time: 1.8666667
value: {fileID: 7641797402717130384, guid: fe0da625d2043344dabbbd3b4b9bad57, type: 3}
- time: 1.9
value: {fileID: -5749066202263594883, guid: 052b3b9d588f899458b26937a86c14a8, type: 3}
- time: 1.9166666
value: {fileID: -4334950345164473505, guid: 3c2093a273dda554f85bb9ef0a3e9f1b, type: 3}
- time: 1.95
value: {fileID: -2731459448565533766, guid: 9f919e4f8647a4b4cb9ddec5f1b3ab74, type: 3}
- time: 1.9666667
value: {fileID: -952861716737482772, guid: 878ef6cb320c1304599866069205d4d3, type: 3}
- time: 2
value: {fileID: -7480260193772456602, guid: ceb7b75e494b05241be795e6021c7e3d, type: 3}
- time: 2.0333333
value: {fileID: 3315436927602067062, guid: 09adc4b6322487047b6331ecc41e5670, type: 3}
- time: 2.05
value: {fileID: -8960640484463501028, guid: e181324922fc08e4980a397a6f968f65, type: 3}
- time: 2.0833333
value: {fileID: -3783765882821197271, guid: 934b4ac2d47a6b843afbe30933fb90e1, type: 3}
- time: 2.1
value: {fileID: 5130296087082377831, guid: 0aa2c2c8d97f10b48b8bc4e15997a92e, type: 3}
- time: 2.1333334
value: {fileID: 5948730499106172589, guid: 7ec27709b5a4bc94f98157b835a54b35, type: 3}
- time: 2.1666667
value: {fileID: -2065247027929301537, guid: dd03645110d7e9f4bb6f144f2c780b47, type: 3}
- time: 2.1833334
value: {fileID: 3471553910959967720, guid: 8ac6625382e350840826f4efb6f52551, type: 3}
- time: 2.2166667
value: {fileID: 7147884992925462185, guid: e7b820761fbece1458ea9f64be6ae167, type: 3}
- time: 2.25
value: {fileID: 7776075522558150528, guid: e9e9c4d382cda2843b787e0da8dfab7e, type: 3}
- time: 2.2666667
value: {fileID: 7700255932872927287, guid: 3384d380475fd654b9a3b1e15b76d475, type: 3}
- time: 2.3
value: {fileID: -338793785751469368, guid: 91a02e372c6c02747bf329eac826b048, type: 3}
- time: 2.3166666
value: {fileID: 748982394305440746, guid: ec6bf3a406942dd40a42c517ce2b58a9, type: 3}
- time: 2.35
value: {fileID: -3656019134591971382, guid: f54770506a3125d46b2ce52f81ae46bf, type: 3}
- time: 2.3833334
value: {fileID: 399832807898711558, guid: 1a65422daae1978468da54481e867fbb, type: 3}
- time: 2.4
value: {fileID: -521352512460838309, guid: c51cea5f7e1fe9d4fa4d4a71c35fec0f, type: 3}
- time: 2.4333334
value: {fileID: -6162581824837280814, guid: 7d8992cf1f102374e9d4b4466449cb18, type: 3}
- time: 2.4666667
value: {fileID: 1192263849535811214, guid: 1428ae5fee830434d97694e08cc6fa93, type: 3}
- time: 2.4833333
value: {fileID: 603205461529862287, guid: e36dcd554754c7142a1168767b1eea48, type: 3}
- time: 2.5166667
value: {fileID: -7134425024940483597, guid: 55b3350228bdcfb4e859c0cf3738cb1b, type: 3}
- time: 2.5333333
value: {fileID: 9074942846105668508, guid: cc41c9176910bf04f9133e766a9cb35f, type: 3}
- time: 2.5666666
value: {fileID: 1087911144614698270, guid: 3b1b13ace35694445b8df45364b290d3, type: 3}
- time: 2.6
value: {fileID: 1061912376056657379, guid: 65bbfdf0ca4eb6f41b49e66866b3528f, type: 3}
- time: 2.6166666
value: {fileID: -8405451713087066662, guid: 16d236293ed9f8b4791256dd4a7a7d97, type: 3}
- time: 2.65
value: {fileID: -2728002667866796986, guid: 5dd035e3268f06b4490814095546d7a0, type: 3}
- time: 2.6833334
value: {fileID: -9090621488756246360, guid: d642b7370589bbe4f81757522b9f3a72, type: 3}
- time: 2.7
value: {fileID: 9195924949492418072, guid: 0e60f0d1d8ec32442a528b11e0852015, type: 3}
- time: 2.7333333
value: {fileID: -3840918005068063611, guid: 9c93d8429b650734b872d70607363ee5, type: 3}
- time: 2.75
value: {fileID: -916943215596444842, guid: 91288e6d7daba8f4ca88dc5150d41b55, type: 3}
- time: 2.7833333
value: {fileID: 2606219628006263488, guid: 942f77cb4ae73da47a8b7af348f236aa, type: 3}
- time: 2.8166666
value: {fileID: -8690719280946211179, guid: 1e892f29f321c6a45aba7c9dfa9b08ec, type: 3}
- time: 2.8333333
value: {fileID: 8492566056286881410, guid: 862829a630bb167449a9fe692eb9f3a0, type: 3}
- time: 2.8666666
value: {fileID: -8216589113262201667, guid: 3157f4f8565963f47ad993aa47b02377, type: 3}
- time: 2.9
value: {fileID: 9170008397909679653, guid: f489c6b7d06a448418cf7d89b710b4bd, type: 3}
- time: 2.9166667
value: {fileID: 3263983331356569123, guid: d5e07472fa08e1a4db5c60556e8b51d7, type: 3}
- time: 2.95
value: {fileID: -4625235417430191742, guid: 0eda17e0697f6644db04528074f8af48, type: 3}
- time: 2.9666667
value: {fileID: -1908371869855739119, guid: c2f8da7be564f7a4fb4787e229832631, type: 3}
- time: 3
value: {fileID: -3962439219219485336, guid: f8baa13b7c91b7c41a50b323f2615cc7, type: 3}
attribute: m_Sprite
path: field
classID: 114
script: {fileID: 11500000, guid: fe87c0e1cc204ed48ad3b37840f39efc, type: 3}
flags: 2
m_SampleRate: 60
m_WrapMode: 0
m_Bounds:
m_Center: {x: 0, y: 0, z: 0}
m_Extent: {x: 0, y: 0, z: 0}
m_ClipBindingConstant:
genericBindings:
- serializedVersion: 2
path: 1542800728
attribute: 2015549526
script: {fileID: 11500000, guid: fe87c0e1cc204ed48ad3b37840f39efc, type: 3}
typeID: 114
customType: 0
isPPtrCurve: 1
isIntCurve: 0
isSerializeReferenceCurve: 0
pptrCurveMapping:
- {fileID: 2326327491318180270, guid: b6c56c1425fa2f8408c994c527e26a90, type: 3}
- {fileID: 3039656268719684704, guid: 57ade1617fe03ce47973f453d69b3480, type: 3}
- {fileID: -9148344310071500359, guid: 5856e0a6a3e22894db0495cb4f47090b, type: 3}
- {fileID: -8946820737381054217, guid: c1ed0abc4be1a814089f41698b1a6ae9, type: 3}
- {fileID: 1169171792133349783, guid: d661c41bdd54f0749a3f6ce9b76922b9, type: 3}
- {fileID: -9162835414837137971, guid: 1e52d3e76a6ad9240b43596c128083c2, type: 3}
- {fileID: 4054532105436495736, guid: ffdf322806b69f14184628cb835d4651, type: 3}
- {fileID: -2769560261860674534, guid: bf96e93cb75a36b4d9e7bd6be37c49c1, type: 3}
- {fileID: 337469173700556176, guid: 0380b9106f20e364f9829e45849b93b5, type: 3}
- {fileID: -1893092822091598629, guid: 2889f9b33b3507d4596f7460716eb88a, type: 3}
- {fileID: -3779762386179194896, guid: dd8d5e7fd43d915419a9bc4c4a13c87f, type: 3}
- {fileID: 1568047047368444430, guid: 58f8fdb8db035fe42925165db312de6f, type: 3}
- {fileID: 3341768276131303601, guid: 571163594414f9940a46e54e3a28ba3e, type: 3}
- {fileID: -3274699238553858469, guid: c3ea11aecfb35934fbd6ebfd75367b7f, type: 3}
- {fileID: -2904124417626424539, guid: cbb0ccfaf845bcf4b9b318e7e17b2386, type: 3}
- {fileID: 7807152604696158922, guid: 648f5791cf82b074eb22242756e7a84e, type: 3}
- {fileID: -7436839558645834474, guid: ddc6d2f24c0fc464089d070137d69153, type: 3}
- {fileID: 8094720510830227213, guid: c8cf7aae8cc60584989fd3e5780d9ada, type: 3}
- {fileID: 7779922750506681629, guid: de8f5c49b9afd07468509051e66d2cdf, type: 3}
- {fileID: 3496087471285781191, guid: 4e82a0023f2925e4095a945e6cdd7561, type: 3}
- {fileID: 8638417948329565305, guid: ea3ab7e6dc988d84d9f772ca6247306c, type: 3}
- {fileID: -271827495750292581, guid: 6d2967a2a13b6bf4c944e5ba6deec0c9, type: 3}
- {fileID: -3388446827607515280, guid: 3f05fc19723cfe348825f234e8f6dc95, type: 3}
- {fileID: -1666824402963536844, guid: 8869e8a80c6427347885e0af01056060, type: 3}
- {fileID: -8937177477147073390, guid: 23b9137b4ee9787419733f698cdf432a, type: 3}
- {fileID: -8799646602856602245, guid: caa45998ad7697c439e4394aad15e4ce, type: 3}
- {fileID: -2919293107161874442, guid: f6a7a1413dd7e574db87a9e167b55107, type: 3}
- {fileID: -4394205086732167005, guid: cdbe41dacfeb21b44b800a49ea2b81fb, type: 3}
- {fileID: 5667663509541448309, guid: c70f3e48526c5094a86cd4e39ba85b3e, type: 3}
- {fileID: 7348336625229709678, guid: 189527c7e3a0a004db2872b0a8e3ceb5, type: 3}
- {fileID: 5931598933246611655, guid: 6a5cac00dbe17394b801517dc895647d, type: 3}
- {fileID: 8452745832453081500, guid: 280d3c25be2edeb4fa02d7dd04a03c9a, type: 3}
- {fileID: -3621795988406732249, guid: f63b7fb53f154d74e8ec8146aca6048c, type: 3}
- {fileID: 2240764819728979505, guid: 0e16df8ab797e6241ae23dd4e6ce487b, type: 3}
- {fileID: 7879484713341989712, guid: 700fd15bd9288ed45b5714d9edc52b3b, type: 3}
- {fileID: -9213452353189187973, guid: f1736e31cb0f483469813ba9b38b565f, type: 3}
- {fileID: 2111467077804923315, guid: f88d784d9e7233e4c87665470234f383, type: 3}
- {fileID: -874371296305861922, guid: 4353b503ea33bad4e8bd869ded3100b1, type: 3}
- {fileID: -4722877178089714693, guid: d258334f319668a428336f65d585323d, type: 3}
- {fileID: 974538412794390107, guid: 9129d4098d9b04447914c959d45da0f1, type: 3}
- {fileID: 1355229876367979772, guid: 95a9226d51366fc4fa6eb18e2bafd39d, type: 3}
- {fileID: 7670519301962771510, guid: 9f9a286b35209e143a2f188b2c11433d, type: 3}
- {fileID: 6072851112962974044, guid: f7bce4982cec5fc468e902196fae045f, type: 3}
- {fileID: -6319862089727399332, guid: be8eac887eec56f4297b6e510b403dcd, type: 3}
- {fileID: -932602025479058729, guid: c4c5a559eb5006e47b1bd6e98976d9de, type: 3}
- {fileID: -7645832949135137003, guid: d4c174fae4c6e0d4ca27a5f3b7730cae, type: 3}
- {fileID: -2393745200414661269, guid: f2e36a58d1e243e49b88241ee20c4877, type: 3}
- {fileID: 8977753790170574155, guid: ffe7d49e866535c4a958570317642a95, type: 3}
- {fileID: 1589886341371401149, guid: 37bebf89626e0f448b58b969c93d40e0, type: 3}
- {fileID: 1958469704995616933, guid: cb546a3527c851741b9212711d924a7b, type: 3}
- {fileID: -1663287010409347934, guid: 76bbadb6b73973a41991e331f2a30d0b, type: 3}
- {fileID: 8931199389144512364, guid: 2f95eff7070e49b429851d2b3caaef25, type: 3}
- {fileID: -6375165851556118606, guid: f8882cd79155d3d40b015470c68b0e08, type: 3}
- {fileID: 2605750455627557777, guid: fd8f39578bf065e4c91ebcf5573f9efe, type: 3}
- {fileID: -7979054687685788317, guid: 9361603dbccdeec408a7b2c5e4ada410, type: 3}
- {fileID: -7790389344213789306, guid: 8dd1b385ee834454198b2e1166eb79c8, type: 3}
- {fileID: -8385755097310045752, guid: 5b2adc75c3720904d83e321082194705, type: 3}
- {fileID: 5114680995901985376, guid: 936f75db652ba3745a81715cbc04f234, type: 3}
- {fileID: 6219192158437786728, guid: e6bf6c1c3a65cab4288b8cc2fc87d781, type: 3}
- {fileID: -8483101290065073045, guid: 460b39275c0556640a8ab23969fe9835, type: 3}
- {fileID: -5795086960448516603, guid: c5d1f615ddbd6344ca8fb0d5117ac417, type: 3}
- {fileID: -7690586406086400816, guid: 7401181cefca1f14b8efcf047d133d22, type: 3}
- {fileID: 7994291799538021827, guid: 1fe673cd12f828e4cbc61380eae47dd6, type: 3}
- {fileID: -4622645856484230464, guid: 94e4567f457e037408f3260d5900d576, type: 3}
- {fileID: -7119226307677305272, guid: d59f1a8ea5a27d044be1a889967031cb, type: 3}
- {fileID: -2510434210989532096, guid: 2a58d9c6fd7e10f43b009158bed30950, type: 3}
- {fileID: -1900014500118246637, guid: 4efc235d4ede2274fb505615a66d05e0, type: 3}
- {fileID: -5548813928269055359, guid: d30d839f35579f04eb735a7f0ce2714b, type: 3}
- {fileID: -8779485291810269718, guid: 1cc644f034f91e04e9160a1bca22e24d, type: 3}
- {fileID: 7641797402717130384, guid: fe0da625d2043344dabbbd3b4b9bad57, type: 3}
- {fileID: -5749066202263594883, guid: 052b3b9d588f899458b26937a86c14a8, type: 3}
- {fileID: -4334950345164473505, guid: 3c2093a273dda554f85bb9ef0a3e9f1b, type: 3}
- {fileID: -2731459448565533766, guid: 9f919e4f8647a4b4cb9ddec5f1b3ab74, type: 3}
- {fileID: -952861716737482772, guid: 878ef6cb320c1304599866069205d4d3, type: 3}
- {fileID: -7480260193772456602, guid: ceb7b75e494b05241be795e6021c7e3d, type: 3}
- {fileID: 3315436927602067062, guid: 09adc4b6322487047b6331ecc41e5670, type: 3}
- {fileID: -8960640484463501028, guid: e181324922fc08e4980a397a6f968f65, type: 3}
- {fileID: -3783765882821197271, guid: 934b4ac2d47a6b843afbe30933fb90e1, type: 3}
- {fileID: 5130296087082377831, guid: 0aa2c2c8d97f10b48b8bc4e15997a92e, type: 3}
- {fileID: 5948730499106172589, guid: 7ec27709b5a4bc94f98157b835a54b35, type: 3}
- {fileID: -2065247027929301537, guid: dd03645110d7e9f4bb6f144f2c780b47, type: 3}
- {fileID: 3471553910959967720, guid: 8ac6625382e350840826f4efb6f52551, type: 3}
- {fileID: 7147884992925462185, guid: e7b820761fbece1458ea9f64be6ae167, type: 3}
- {fileID: 7776075522558150528, guid: e9e9c4d382cda2843b787e0da8dfab7e, type: 3}
- {fileID: 7700255932872927287, guid: 3384d380475fd654b9a3b1e15b76d475, type: 3}
- {fileID: -338793785751469368, guid: 91a02e372c6c02747bf329eac826b048, type: 3}
- {fileID: 748982394305440746, guid: ec6bf3a406942dd40a42c517ce2b58a9, type: 3}
- {fileID: -3656019134591971382, guid: f54770506a3125d46b2ce52f81ae46bf, type: 3}
- {fileID: 399832807898711558, guid: 1a65422daae1978468da54481e867fbb, type: 3}
- {fileID: -521352512460838309, guid: c51cea5f7e1fe9d4fa4d4a71c35fec0f, type: 3}
- {fileID: -6162581824837280814, guid: 7d8992cf1f102374e9d4b4466449cb18, type: 3}
- {fileID: 1192263849535811214, guid: 1428ae5fee830434d97694e08cc6fa93, type: 3}
- {fileID: 603205461529862287, guid: e36dcd554754c7142a1168767b1eea48, type: 3}
- {fileID: -7134425024940483597, guid: 55b3350228bdcfb4e859c0cf3738cb1b, type: 3}
- {fileID: 9074942846105668508, guid: cc41c9176910bf04f9133e766a9cb35f, type: 3}
- {fileID: 1087911144614698270, guid: 3b1b13ace35694445b8df45364b290d3, type: 3}
- {fileID: 1061912376056657379, guid: 65bbfdf0ca4eb6f41b49e66866b3528f, type: 3}
- {fileID: -8405451713087066662, guid: 16d236293ed9f8b4791256dd4a7a7d97, type: 3}
- {fileID: -2728002667866796986, guid: 5dd035e3268f06b4490814095546d7a0, type: 3}
- {fileID: -9090621488756246360, guid: d642b7370589bbe4f81757522b9f3a72, type: 3}
- {fileID: 9195924949492418072, guid: 0e60f0d1d8ec32442a528b11e0852015, type: 3}
- {fileID: -3840918005068063611, guid: 9c93d8429b650734b872d70607363ee5, type: 3}
- {fileID: -916943215596444842, guid: 91288e6d7daba8f4ca88dc5150d41b55, type: 3}
- {fileID: 2606219628006263488, guid: 942f77cb4ae73da47a8b7af348f236aa, type: 3}
- {fileID: -8690719280946211179, guid: 1e892f29f321c6a45aba7c9dfa9b08ec, type: 3}
- {fileID: 8492566056286881410, guid: 862829a630bb167449a9fe692eb9f3a0, type: 3}
- {fileID: -8216589113262201667, guid: 3157f4f8565963f47ad993aa47b02377, type: 3}
- {fileID: 9170008397909679653, guid: f489c6b7d06a448418cf7d89b710b4bd, type: 3}
- {fileID: 3263983331356569123, guid: d5e07472fa08e1a4db5c60556e8b51d7, type: 3}
- {fileID: -4625235417430191742, guid: 0eda17e0697f6644db04528074f8af48, type: 3}
- {fileID: -1908371869855739119, guid: c2f8da7be564f7a4fb4787e229832631, type: 3}
- {fileID: -3962439219219485336, guid: f8baa13b7c91b7c41a50b323f2615cc7, type: 3}
m_AnimationClipSettings:
serializedVersion: 2
m_AdditiveReferencePoseClip: {fileID: 0}
m_AdditiveReferencePoseTime: 0
m_StartTime: 0
m_StopTime: 3.0166667
m_OrientationOffsetY: 0
m_Level: 0
m_CycleOffset: 0
m_HasAdditiveReferencePose: 0
m_LoopTime: 1
m_LoopBlend: 0
m_LoopBlendOrientation: 0
m_LoopBlendPositionY: 0
m_LoopBlendPositionXZ: 0
m_KeepOriginalOrientation: 0
m_KeepOriginalPositionY: 1
m_KeepOriginalPositionXZ: 0
m_HeightFromFeet: 0
m_Mirror: 0
m_EditorCurves: []
m_EulerEditorCurves: []
m_HasGenericRootTransform: 0
m_HasMotionFloatCurves: 0
m_Events: []
@@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 012b635d069efe04eb565eb2f83ff075
NativeFormatImporter:
externalObjects: {}
mainObjectFileID: 7400000
userData:
assetBundleName:
assetBundleVariant:
Binary file not shown.

After

Width:  |  Height:  |  Size: 106 KiB

@@ -0,0 +1,156 @@
fileFormatVersion: 2
guid: b6c56c1425fa2f8408c994c527e26a90
TextureImporter:
internalIDToNameTable:
- first:
213: 2326327491318180270
second: how_to_play_goal0001_0
externalObjects: {}
serializedVersion: 13
mipmaps:
mipMapMode: 0
enableMipMap: 0
sRGBTexture: 1
linearTexture: 0
fadeOut: 0
borderMipMap: 0
mipMapsPreserveCoverage: 0
alphaTestReferenceValue: 0.5
mipMapFadeDistanceStart: 1
mipMapFadeDistanceEnd: 3
bumpmap:
convertToNormalMap: 0
externalNormalMap: 0
heightScale: 0.25
normalMapFilter: 0
flipGreenChannel: 0
isReadable: 0
streamingMipmaps: 0
streamingMipmapsPriority: 0
vTOnly: 0
ignoreMipmapLimit: 0
grayScaleToAlpha: 0
generateCubemap: 6
cubemapConvolution: 0
seamlessCubemap: 0
textureFormat: 1
maxTextureSize: 2048
textureSettings:
serializedVersion: 2
filterMode: 1
aniso: 1
mipBias: 0
wrapU: 1
wrapV: 1
wrapW: 1
nPOTScale: 0
lightmap: 0
compressionQuality: 50
spriteMode: 2
spriteExtrude: 1
spriteMeshType: 1
alignment: 0
spritePivot: {x: 0.5, y: 0.5}
spritePixelsToUnits: 100
spriteBorder: {x: 0, y: 0, z: 0, w: 0}
spriteGenerateFallbackPhysicsShape: 1
alphaUsage: 1
alphaIsTransparency: 1
spriteTessellationDetail: -1
textureType: 8
textureShape: 1
singleChannelComponent: 0
flipbookRows: 1
flipbookColumns: 1
maxTextureSizeSet: 0
compressionQualitySet: 0
textureFormatSet: 0
ignorePngGamma: 0
applyGammaDecoding: 0
swizzle: 50462976
cookieLightType: 0
platformSettings:
- serializedVersion: 4
buildTarget: DefaultTexturePlatform
maxTextureSize: 1024
resizeAlgorithm: 0
textureFormat: -1
textureCompression: 1
compressionQuality: 50
crunchedCompression: 1
allowsAlphaSplitting: 0
overridden: 0
ignorePlatformSupport: 0
androidETC2FallbackOverride: 0
forceMaximumCompressionQuality_BC6H_BC7: 0
- serializedVersion: 4
buildTarget: Standalone
maxTextureSize: 2048
resizeAlgorithm: 0
textureFormat: -1
textureCompression: 1
compressionQuality: 50
crunchedCompression: 0
allowsAlphaSplitting: 0
overridden: 0
ignorePlatformSupport: 0
androidETC2FallbackOverride: 0
forceMaximumCompressionQuality_BC6H_BC7: 0
- serializedVersion: 4
buildTarget: Android
maxTextureSize: 2048
resizeAlgorithm: 0
textureFormat: -1
textureCompression: 1
compressionQuality: 50
crunchedCompression: 0
allowsAlphaSplitting: 0
overridden: 0
ignorePlatformSupport: 0
androidETC2FallbackOverride: 0
forceMaximumCompressionQuality_BC6H_BC7: 0
spriteSheet:
serializedVersion: 2
sprites:
- serializedVersion: 2
name: how_to_play_goal0001_0
rect:
serializedVersion: 2
x: 0
y: 0
width: 1080
height: 1920
alignment: 0
pivot: {x: 0, y: 0}
border: {x: 0, y: 0, z: 0, w: 0}
customData:
outline: []
physicsShape: []
tessellationDetail: -1
bones: []
spriteID: ea9ee372786c84020800000000000000
internalID: 2326327491318180270
vertices: []
indices:
edges: []
weights: []
outline: []
customData:
physicsShape: []
bones: []
spriteID:
internalID: 0
vertices: []
indices:
edges: []
weights: []
secondaryTextures: []
spriteCustomMetadata:
entries: []
nameFileIdTable:
how_to_play_goal0001_0: 2326327491318180270
mipmapLimitGroupName:
pSDRemoveMatte: 0
userData:
assetBundleName:
assetBundleVariant:
Binary file not shown.

After

Width:  |  Height:  |  Size: 117 KiB

@@ -0,0 +1,156 @@
fileFormatVersion: 2
guid: 57ade1617fe03ce47973f453d69b3480
TextureImporter:
internalIDToNameTable:
- first:
213: 3039656268719684704
second: how_to_play_goal0002_0
externalObjects: {}
serializedVersion: 13
mipmaps:
mipMapMode: 0
enableMipMap: 0
sRGBTexture: 1
linearTexture: 0
fadeOut: 0
borderMipMap: 0
mipMapsPreserveCoverage: 0
alphaTestReferenceValue: 0.5
mipMapFadeDistanceStart: 1
mipMapFadeDistanceEnd: 3
bumpmap:
convertToNormalMap: 0
externalNormalMap: 0
heightScale: 0.25
normalMapFilter: 0
flipGreenChannel: 0
isReadable: 0
streamingMipmaps: 0
streamingMipmapsPriority: 0
vTOnly: 0
ignoreMipmapLimit: 0
grayScaleToAlpha: 0
generateCubemap: 6
cubemapConvolution: 0
seamlessCubemap: 0
textureFormat: 1
maxTextureSize: 2048
textureSettings:
serializedVersion: 2
filterMode: 1
aniso: 1
mipBias: 0
wrapU: 1
wrapV: 1
wrapW: 1
nPOTScale: 0
lightmap: 0
compressionQuality: 50
spriteMode: 2
spriteExtrude: 1
spriteMeshType: 1
alignment: 0
spritePivot: {x: 0.5, y: 0.5}
spritePixelsToUnits: 100
spriteBorder: {x: 0, y: 0, z: 0, w: 0}
spriteGenerateFallbackPhysicsShape: 1
alphaUsage: 1
alphaIsTransparency: 1
spriteTessellationDetail: -1
textureType: 8
textureShape: 1
singleChannelComponent: 0
flipbookRows: 1
flipbookColumns: 1
maxTextureSizeSet: 0
compressionQualitySet: 0
textureFormatSet: 0
ignorePngGamma: 0
applyGammaDecoding: 0
swizzle: 50462976
cookieLightType: 0
platformSettings:
- serializedVersion: 4
buildTarget: DefaultTexturePlatform
maxTextureSize: 1024
resizeAlgorithm: 0
textureFormat: -1
textureCompression: 1
compressionQuality: 50
crunchedCompression: 1
allowsAlphaSplitting: 0
overridden: 0
ignorePlatformSupport: 0
androidETC2FallbackOverride: 0
forceMaximumCompressionQuality_BC6H_BC7: 0
- serializedVersion: 4
buildTarget: Standalone
maxTextureSize: 2048
resizeAlgorithm: 0
textureFormat: -1
textureCompression: 1
compressionQuality: 50
crunchedCompression: 0
allowsAlphaSplitting: 0
overridden: 0
ignorePlatformSupport: 0
androidETC2FallbackOverride: 0
forceMaximumCompressionQuality_BC6H_BC7: 0
- serializedVersion: 4
buildTarget: Android
maxTextureSize: 2048
resizeAlgorithm: 0
textureFormat: -1
textureCompression: 1
compressionQuality: 50
crunchedCompression: 0
allowsAlphaSplitting: 0
overridden: 0
ignorePlatformSupport: 0
androidETC2FallbackOverride: 0
forceMaximumCompressionQuality_BC6H_BC7: 0
spriteSheet:
serializedVersion: 2
sprites:
- serializedVersion: 2
name: how_to_play_goal0002_0
rect:
serializedVersion: 2
x: 0
y: 0
width: 1080
height: 1920
alignment: 0
pivot: {x: 0, y: 0}
border: {x: 0, y: 0, z: 0, w: 0}
customData:
outline: []
physicsShape: []
tessellationDetail: -1
bones: []
spriteID: 06c735885470f2a20800000000000000
internalID: 3039656268719684704
vertices: []
indices:
edges: []
weights: []
outline: []
customData:
physicsShape: []
bones: []
spriteID:
internalID: 0
vertices: []
indices:
edges: []
weights: []
secondaryTextures: []
spriteCustomMetadata:
entries: []
nameFileIdTable:
how_to_play_goal0002_0: 3039656268719684704
mipmapLimitGroupName:
pSDRemoveMatte: 0
userData:
assetBundleName:
assetBundleVariant:
Binary file not shown.

After

Width:  |  Height:  |  Size: 141 KiB

@@ -0,0 +1,156 @@
fileFormatVersion: 2
guid: 5856e0a6a3e22894db0495cb4f47090b
TextureImporter:
internalIDToNameTable:
- first:
213: -9148344310071500359
second: how_to_play_goal0003_0
externalObjects: {}
serializedVersion: 13
mipmaps:
mipMapMode: 0
enableMipMap: 0
sRGBTexture: 1
linearTexture: 0
fadeOut: 0
borderMipMap: 0
mipMapsPreserveCoverage: 0
alphaTestReferenceValue: 0.5
mipMapFadeDistanceStart: 1
mipMapFadeDistanceEnd: 3
bumpmap:
convertToNormalMap: 0
externalNormalMap: 0
heightScale: 0.25
normalMapFilter: 0
flipGreenChannel: 0
isReadable: 0
streamingMipmaps: 0
streamingMipmapsPriority: 0
vTOnly: 0
ignoreMipmapLimit: 0
grayScaleToAlpha: 0
generateCubemap: 6
cubemapConvolution: 0
seamlessCubemap: 0
textureFormat: 1
maxTextureSize: 2048
textureSettings:
serializedVersion: 2
filterMode: 1
aniso: 1
mipBias: 0
wrapU: 1
wrapV: 1
wrapW: 1
nPOTScale: 0
lightmap: 0
compressionQuality: 50
spriteMode: 2
spriteExtrude: 1
spriteMeshType: 1
alignment: 0
spritePivot: {x: 0.5, y: 0.5}
spritePixelsToUnits: 100
spriteBorder: {x: 0, y: 0, z: 0, w: 0}
spriteGenerateFallbackPhysicsShape: 1
alphaUsage: 1
alphaIsTransparency: 1
spriteTessellationDetail: -1
textureType: 8
textureShape: 1
singleChannelComponent: 0
flipbookRows: 1
flipbookColumns: 1
maxTextureSizeSet: 0
compressionQualitySet: 0
textureFormatSet: 0
ignorePngGamma: 0
applyGammaDecoding: 0
swizzle: 50462976
cookieLightType: 0
platformSettings:
- serializedVersion: 4
buildTarget: DefaultTexturePlatform
maxTextureSize: 1024
resizeAlgorithm: 0
textureFormat: -1
textureCompression: 1
compressionQuality: 50
crunchedCompression: 1
allowsAlphaSplitting: 0
overridden: 0
ignorePlatformSupport: 0
androidETC2FallbackOverride: 0
forceMaximumCompressionQuality_BC6H_BC7: 0
- serializedVersion: 4
buildTarget: Standalone
maxTextureSize: 2048
resizeAlgorithm: 0
textureFormat: -1
textureCompression: 1
compressionQuality: 50
crunchedCompression: 0
allowsAlphaSplitting: 0
overridden: 0
ignorePlatformSupport: 0
androidETC2FallbackOverride: 0
forceMaximumCompressionQuality_BC6H_BC7: 0
- serializedVersion: 4
buildTarget: Android
maxTextureSize: 2048
resizeAlgorithm: 0
textureFormat: -1
textureCompression: 1
compressionQuality: 50
crunchedCompression: 0
allowsAlphaSplitting: 0
overridden: 0
ignorePlatformSupport: 0
androidETC2FallbackOverride: 0
forceMaximumCompressionQuality_BC6H_BC7: 0
spriteSheet:
serializedVersion: 2
sprites:
- serializedVersion: 2
name: how_to_play_goal0003_0
rect:
serializedVersion: 2
x: 0
y: 0
width: 1080
height: 1920
alignment: 0
pivot: {x: 0, y: 0}
border: {x: 0, y: 0, z: 0, w: 0}
customData:
outline: []
physicsShape: []
tessellationDetail: -1
bones: []
spriteID: 9b1e83be15d8a0180800000000000000
internalID: -9148344310071500359
vertices: []
indices:
edges: []
weights: []
outline: []
customData:
physicsShape: []
bones: []
spriteID:
internalID: 0
vertices: []
indices:
edges: []
weights: []
secondaryTextures: []
spriteCustomMetadata:
entries: []
nameFileIdTable:
how_to_play_goal0003_0: -9148344310071500359
mipmapLimitGroupName:
pSDRemoveMatte: 0
userData:
assetBundleName:
assetBundleVariant:
Binary file not shown.

After

Width:  |  Height:  |  Size: 127 KiB

@@ -0,0 +1,156 @@
fileFormatVersion: 2
guid: c1ed0abc4be1a814089f41698b1a6ae9
TextureImporter:
internalIDToNameTable:
- first:
213: -8946820737381054217
second: how_to_play_goal0004_0
externalObjects: {}
serializedVersion: 13
mipmaps:
mipMapMode: 0
enableMipMap: 0
sRGBTexture: 1
linearTexture: 0
fadeOut: 0
borderMipMap: 0
mipMapsPreserveCoverage: 0
alphaTestReferenceValue: 0.5
mipMapFadeDistanceStart: 1
mipMapFadeDistanceEnd: 3
bumpmap:
convertToNormalMap: 0
externalNormalMap: 0
heightScale: 0.25
normalMapFilter: 0
flipGreenChannel: 0
isReadable: 0
streamingMipmaps: 0
streamingMipmapsPriority: 0
vTOnly: 0
ignoreMipmapLimit: 0
grayScaleToAlpha: 0
generateCubemap: 6
cubemapConvolution: 0
seamlessCubemap: 0
textureFormat: 1
maxTextureSize: 2048
textureSettings:
serializedVersion: 2
filterMode: 1
aniso: 1
mipBias: 0
wrapU: 1
wrapV: 1
wrapW: 1
nPOTScale: 0
lightmap: 0
compressionQuality: 50
spriteMode: 2
spriteExtrude: 1
spriteMeshType: 1
alignment: 0
spritePivot: {x: 0.5, y: 0.5}
spritePixelsToUnits: 100
spriteBorder: {x: 0, y: 0, z: 0, w: 0}
spriteGenerateFallbackPhysicsShape: 1
alphaUsage: 1
alphaIsTransparency: 1
spriteTessellationDetail: -1
textureType: 8
textureShape: 1
singleChannelComponent: 0
flipbookRows: 1
flipbookColumns: 1
maxTextureSizeSet: 0
compressionQualitySet: 0
textureFormatSet: 0
ignorePngGamma: 0
applyGammaDecoding: 0
swizzle: 50462976
cookieLightType: 0
platformSettings:
- serializedVersion: 4
buildTarget: DefaultTexturePlatform
maxTextureSize: 1024
resizeAlgorithm: 0
textureFormat: -1
textureCompression: 1
compressionQuality: 50
crunchedCompression: 1
allowsAlphaSplitting: 0
overridden: 0
ignorePlatformSupport: 0
androidETC2FallbackOverride: 0
forceMaximumCompressionQuality_BC6H_BC7: 0
- serializedVersion: 4
buildTarget: Standalone
maxTextureSize: 2048
resizeAlgorithm: 0
textureFormat: -1
textureCompression: 1
compressionQuality: 50
crunchedCompression: 0
allowsAlphaSplitting: 0
overridden: 0
ignorePlatformSupport: 0
androidETC2FallbackOverride: 0
forceMaximumCompressionQuality_BC6H_BC7: 0
- serializedVersion: 4
buildTarget: Android
maxTextureSize: 2048
resizeAlgorithm: 0
textureFormat: -1
textureCompression: 1
compressionQuality: 50
crunchedCompression: 0
allowsAlphaSplitting: 0
overridden: 0
ignorePlatformSupport: 0
androidETC2FallbackOverride: 0
forceMaximumCompressionQuality_BC6H_BC7: 0
spriteSheet:
serializedVersion: 2
sprites:
- serializedVersion: 2
name: how_to_play_goal0004_0
rect:
serializedVersion: 2
x: 0
y: 0
width: 1080
height: 1920
alignment: 0
pivot: {x: 0, y: 0}
border: {x: 0, y: 0, z: 0, w: 0}
customData:
outline: []
physicsShape: []
tessellationDetail: -1
bones: []
spriteID: 7f8cd4f01f186d380800000000000000
internalID: -8946820737381054217
vertices: []
indices:
edges: []
weights: []
outline: []
customData:
physicsShape: []
bones: []
spriteID:
internalID: 0
vertices: []
indices:
edges: []
weights: []
secondaryTextures: []
spriteCustomMetadata:
entries: []
nameFileIdTable:
how_to_play_goal0004_0: -8946820737381054217
mipmapLimitGroupName:
pSDRemoveMatte: 0
userData:
assetBundleName:
assetBundleVariant:
Binary file not shown.

After

Width:  |  Height:  |  Size: 115 KiB

@@ -0,0 +1,156 @@
fileFormatVersion: 2
guid: d661c41bdd54f0749a3f6ce9b76922b9
TextureImporter:
internalIDToNameTable:
- first:
213: 1169171792133349783
second: how_to_play_goal0005_0
externalObjects: {}
serializedVersion: 13
mipmaps:
mipMapMode: 0
enableMipMap: 0
sRGBTexture: 1
linearTexture: 0
fadeOut: 0
borderMipMap: 0
mipMapsPreserveCoverage: 0
alphaTestReferenceValue: 0.5
mipMapFadeDistanceStart: 1
mipMapFadeDistanceEnd: 3
bumpmap:
convertToNormalMap: 0
externalNormalMap: 0
heightScale: 0.25
normalMapFilter: 0
flipGreenChannel: 0
isReadable: 0
streamingMipmaps: 0
streamingMipmapsPriority: 0
vTOnly: 0
ignoreMipmapLimit: 0
grayScaleToAlpha: 0
generateCubemap: 6
cubemapConvolution: 0
seamlessCubemap: 0
textureFormat: 1
maxTextureSize: 2048
textureSettings:
serializedVersion: 2
filterMode: 1
aniso: 1
mipBias: 0
wrapU: 1
wrapV: 1
wrapW: 1
nPOTScale: 0
lightmap: 0
compressionQuality: 50
spriteMode: 2
spriteExtrude: 1
spriteMeshType: 1
alignment: 0
spritePivot: {x: 0.5, y: 0.5}
spritePixelsToUnits: 100
spriteBorder: {x: 0, y: 0, z: 0, w: 0}
spriteGenerateFallbackPhysicsShape: 1
alphaUsage: 1
alphaIsTransparency: 1
spriteTessellationDetail: -1
textureType: 8
textureShape: 1
singleChannelComponent: 0
flipbookRows: 1
flipbookColumns: 1
maxTextureSizeSet: 0
compressionQualitySet: 0
textureFormatSet: 0
ignorePngGamma: 0
applyGammaDecoding: 0
swizzle: 50462976
cookieLightType: 0
platformSettings:
- serializedVersion: 4
buildTarget: DefaultTexturePlatform
maxTextureSize: 1024
resizeAlgorithm: 0
textureFormat: -1
textureCompression: 1
compressionQuality: 50
crunchedCompression: 1
allowsAlphaSplitting: 0
overridden: 0
ignorePlatformSupport: 0
androidETC2FallbackOverride: 0
forceMaximumCompressionQuality_BC6H_BC7: 0
- serializedVersion: 4
buildTarget: Standalone
maxTextureSize: 2048
resizeAlgorithm: 0
textureFormat: -1
textureCompression: 1
compressionQuality: 50
crunchedCompression: 0
allowsAlphaSplitting: 0
overridden: 0
ignorePlatformSupport: 0
androidETC2FallbackOverride: 0
forceMaximumCompressionQuality_BC6H_BC7: 0
- serializedVersion: 4
buildTarget: Android
maxTextureSize: 2048
resizeAlgorithm: 0
textureFormat: -1
textureCompression: 1
compressionQuality: 50
crunchedCompression: 0
allowsAlphaSplitting: 0
overridden: 0
ignorePlatformSupport: 0
androidETC2FallbackOverride: 0
forceMaximumCompressionQuality_BC6H_BC7: 0
spriteSheet:
serializedVersion: 2
sprites:
- serializedVersion: 2
name: how_to_play_goal0005_0
rect:
serializedVersion: 2
x: 0
y: 0
width: 1080
height: 1920
alignment: 0
pivot: {x: 0, y: 0}
border: {x: 0, y: 0, z: 0, w: 0}
customData:
outline: []
physicsShape: []
tessellationDetail: -1
bones: []
spriteID: 791e387ec8bb93010800000000000000
internalID: 1169171792133349783
vertices: []
indices:
edges: []
weights: []
outline: []
customData:
physicsShape: []
bones: []
spriteID:
internalID: 0
vertices: []
indices:
edges: []
weights: []
secondaryTextures: []
spriteCustomMetadata:
entries: []
nameFileIdTable:
how_to_play_goal0005_0: 1169171792133349783
mipmapLimitGroupName:
pSDRemoveMatte: 0
userData:
assetBundleName:
assetBundleVariant:
Binary file not shown.

After

Width:  |  Height:  |  Size: 94 KiB

@@ -0,0 +1,156 @@
fileFormatVersion: 2
guid: 1e52d3e76a6ad9240b43596c128083c2
TextureImporter:
internalIDToNameTable:
- first:
213: -9162835414837137971
second: how_to_play_goal0006_0
externalObjects: {}
serializedVersion: 13
mipmaps:
mipMapMode: 0
enableMipMap: 0
sRGBTexture: 1
linearTexture: 0
fadeOut: 0
borderMipMap: 0
mipMapsPreserveCoverage: 0
alphaTestReferenceValue: 0.5
mipMapFadeDistanceStart: 1
mipMapFadeDistanceEnd: 3
bumpmap:
convertToNormalMap: 0
externalNormalMap: 0
heightScale: 0.25
normalMapFilter: 0
flipGreenChannel: 0
isReadable: 0
streamingMipmaps: 0
streamingMipmapsPriority: 0
vTOnly: 0
ignoreMipmapLimit: 0
grayScaleToAlpha: 0
generateCubemap: 6
cubemapConvolution: 0
seamlessCubemap: 0
textureFormat: 1
maxTextureSize: 2048
textureSettings:
serializedVersion: 2
filterMode: 1
aniso: 1
mipBias: 0
wrapU: 1
wrapV: 1
wrapW: 1
nPOTScale: 0
lightmap: 0
compressionQuality: 50
spriteMode: 2
spriteExtrude: 1
spriteMeshType: 1
alignment: 0
spritePivot: {x: 0.5, y: 0.5}
spritePixelsToUnits: 100
spriteBorder: {x: 0, y: 0, z: 0, w: 0}
spriteGenerateFallbackPhysicsShape: 1
alphaUsage: 1
alphaIsTransparency: 1
spriteTessellationDetail: -1
textureType: 8
textureShape: 1
singleChannelComponent: 0
flipbookRows: 1
flipbookColumns: 1
maxTextureSizeSet: 0
compressionQualitySet: 0
textureFormatSet: 0
ignorePngGamma: 0
applyGammaDecoding: 0
swizzle: 50462976
cookieLightType: 0
platformSettings:
- serializedVersion: 4
buildTarget: DefaultTexturePlatform
maxTextureSize: 1024
resizeAlgorithm: 0
textureFormat: -1
textureCompression: 1
compressionQuality: 50
crunchedCompression: 1
allowsAlphaSplitting: 0
overridden: 0
ignorePlatformSupport: 0
androidETC2FallbackOverride: 0
forceMaximumCompressionQuality_BC6H_BC7: 0
- serializedVersion: 4
buildTarget: Standalone
maxTextureSize: 2048
resizeAlgorithm: 0
textureFormat: -1
textureCompression: 1
compressionQuality: 50
crunchedCompression: 0
allowsAlphaSplitting: 0
overridden: 0
ignorePlatformSupport: 0
androidETC2FallbackOverride: 0
forceMaximumCompressionQuality_BC6H_BC7: 0
- serializedVersion: 4
buildTarget: Android
maxTextureSize: 2048
resizeAlgorithm: 0
textureFormat: -1
textureCompression: 1
compressionQuality: 50
crunchedCompression: 0
allowsAlphaSplitting: 0
overridden: 0
ignorePlatformSupport: 0
androidETC2FallbackOverride: 0
forceMaximumCompressionQuality_BC6H_BC7: 0
spriteSheet:
serializedVersion: 2
sprites:
- serializedVersion: 2
name: how_to_play_goal0006_0
rect:
serializedVersion: 2
x: 0
y: 0
width: 1080
height: 1920
alignment: 0
pivot: {x: 0, y: 0}
border: {x: 0, y: 0, z: 0, w: 0}
customData:
outline: []
physicsShape: []
tessellationDetail: -1
bones: []
spriteID: dcd634bacb117d080800000000000000
internalID: -9162835414837137971
vertices: []
indices:
edges: []
weights: []
outline: []
customData:
physicsShape: []
bones: []
spriteID:
internalID: 0
vertices: []
indices:
edges: []
weights: []
secondaryTextures: []
spriteCustomMetadata:
entries: []
nameFileIdTable:
how_to_play_goal0006_0: -9162835414837137971
mipmapLimitGroupName:
pSDRemoveMatte: 0
userData:
assetBundleName:
assetBundleVariant:
Binary file not shown.

After

Width:  |  Height:  |  Size: 80 KiB

@@ -0,0 +1,156 @@
fileFormatVersion: 2
guid: ffdf322806b69f14184628cb835d4651
TextureImporter:
internalIDToNameTable:
- first:
213: 4054532105436495736
second: how_to_play_goal0007_0
externalObjects: {}
serializedVersion: 13
mipmaps:
mipMapMode: 0
enableMipMap: 0
sRGBTexture: 1
linearTexture: 0
fadeOut: 0
borderMipMap: 0
mipMapsPreserveCoverage: 0
alphaTestReferenceValue: 0.5
mipMapFadeDistanceStart: 1
mipMapFadeDistanceEnd: 3
bumpmap:
convertToNormalMap: 0
externalNormalMap: 0
heightScale: 0.25
normalMapFilter: 0
flipGreenChannel: 0
isReadable: 0
streamingMipmaps: 0
streamingMipmapsPriority: 0
vTOnly: 0
ignoreMipmapLimit: 0
grayScaleToAlpha: 0
generateCubemap: 6
cubemapConvolution: 0
seamlessCubemap: 0
textureFormat: 1
maxTextureSize: 2048
textureSettings:
serializedVersion: 2
filterMode: 1
aniso: 1
mipBias: 0
wrapU: 1
wrapV: 1
wrapW: 1
nPOTScale: 0
lightmap: 0
compressionQuality: 50
spriteMode: 2
spriteExtrude: 1
spriteMeshType: 1
alignment: 0
spritePivot: {x: 0.5, y: 0.5}
spritePixelsToUnits: 100
spriteBorder: {x: 0, y: 0, z: 0, w: 0}
spriteGenerateFallbackPhysicsShape: 1
alphaUsage: 1
alphaIsTransparency: 1
spriteTessellationDetail: -1
textureType: 8
textureShape: 1
singleChannelComponent: 0
flipbookRows: 1
flipbookColumns: 1
maxTextureSizeSet: 0
compressionQualitySet: 0
textureFormatSet: 0
ignorePngGamma: 0
applyGammaDecoding: 0
swizzle: 50462976
cookieLightType: 0
platformSettings:
- serializedVersion: 4
buildTarget: DefaultTexturePlatform
maxTextureSize: 1024
resizeAlgorithm: 0
textureFormat: -1
textureCompression: 1
compressionQuality: 50
crunchedCompression: 1
allowsAlphaSplitting: 0
overridden: 0
ignorePlatformSupport: 0
androidETC2FallbackOverride: 0
forceMaximumCompressionQuality_BC6H_BC7: 0
- serializedVersion: 4
buildTarget: Standalone
maxTextureSize: 2048
resizeAlgorithm: 0
textureFormat: -1
textureCompression: 1
compressionQuality: 50
crunchedCompression: 0
allowsAlphaSplitting: 0
overridden: 0
ignorePlatformSupport: 0
androidETC2FallbackOverride: 0
forceMaximumCompressionQuality_BC6H_BC7: 0
- serializedVersion: 4
buildTarget: Android
maxTextureSize: 2048
resizeAlgorithm: 0
textureFormat: -1
textureCompression: 1
compressionQuality: 50
crunchedCompression: 0
allowsAlphaSplitting: 0
overridden: 0
ignorePlatformSupport: 0
androidETC2FallbackOverride: 0
forceMaximumCompressionQuality_BC6H_BC7: 0
spriteSheet:
serializedVersion: 2
sprites:
- serializedVersion: 2
name: how_to_play_goal0007_0
rect:
serializedVersion: 2
x: 0
y: 0
width: 1080
height: 1920
alignment: 0
pivot: {x: 0, y: 0}
border: {x: 0, y: 0, z: 0, w: 0}
customData:
outline: []
physicsShape: []
tessellationDetail: -1
bones: []
spriteID: 87f75f2d777944830800000000000000
internalID: 4054532105436495736
vertices: []
indices:
edges: []
weights: []
outline: []
customData:
physicsShape: []
bones: []
spriteID:
internalID: 0
vertices: []
indices:
edges: []
weights: []
secondaryTextures: []
spriteCustomMetadata:
entries: []
nameFileIdTable:
how_to_play_goal0007_0: 4054532105436495736
mipmapLimitGroupName:
pSDRemoveMatte: 0
userData:
assetBundleName:
assetBundleVariant:
Binary file not shown.

After

Width:  |  Height:  |  Size: 72 KiB

@@ -0,0 +1,156 @@
fileFormatVersion: 2
guid: bf96e93cb75a36b4d9e7bd6be37c49c1
TextureImporter:
internalIDToNameTable:
- first:
213: -2769560261860674534
second: how_to_play_goal0008_0
externalObjects: {}
serializedVersion: 13
mipmaps:
mipMapMode: 0
enableMipMap: 0
sRGBTexture: 1
linearTexture: 0
fadeOut: 0
borderMipMap: 0
mipMapsPreserveCoverage: 0
alphaTestReferenceValue: 0.5
mipMapFadeDistanceStart: 1
mipMapFadeDistanceEnd: 3
bumpmap:
convertToNormalMap: 0
externalNormalMap: 0
heightScale: 0.25
normalMapFilter: 0
flipGreenChannel: 0
isReadable: 0
streamingMipmaps: 0
streamingMipmapsPriority: 0
vTOnly: 0
ignoreMipmapLimit: 0
grayScaleToAlpha: 0
generateCubemap: 6
cubemapConvolution: 0
seamlessCubemap: 0
textureFormat: 1
maxTextureSize: 2048
textureSettings:
serializedVersion: 2
filterMode: 1
aniso: 1
mipBias: 0
wrapU: 1
wrapV: 1
wrapW: 1
nPOTScale: 0
lightmap: 0
compressionQuality: 50
spriteMode: 2
spriteExtrude: 1
spriteMeshType: 1
alignment: 0
spritePivot: {x: 0.5, y: 0.5}
spritePixelsToUnits: 100
spriteBorder: {x: 0, y: 0, z: 0, w: 0}
spriteGenerateFallbackPhysicsShape: 1
alphaUsage: 1
alphaIsTransparency: 1
spriteTessellationDetail: -1
textureType: 8
textureShape: 1
singleChannelComponent: 0
flipbookRows: 1
flipbookColumns: 1
maxTextureSizeSet: 0
compressionQualitySet: 0
textureFormatSet: 0
ignorePngGamma: 0
applyGammaDecoding: 0
swizzle: 50462976
cookieLightType: 0
platformSettings:
- serializedVersion: 4
buildTarget: DefaultTexturePlatform
maxTextureSize: 1024
resizeAlgorithm: 0
textureFormat: -1
textureCompression: 1
compressionQuality: 50
crunchedCompression: 1
allowsAlphaSplitting: 0
overridden: 0
ignorePlatformSupport: 0
androidETC2FallbackOverride: 0
forceMaximumCompressionQuality_BC6H_BC7: 0
- serializedVersion: 4
buildTarget: Standalone
maxTextureSize: 2048
resizeAlgorithm: 0
textureFormat: -1
textureCompression: 1
compressionQuality: 50
crunchedCompression: 0
allowsAlphaSplitting: 0
overridden: 0
ignorePlatformSupport: 0
androidETC2FallbackOverride: 0
forceMaximumCompressionQuality_BC6H_BC7: 0
- serializedVersion: 4
buildTarget: Android
maxTextureSize: 2048
resizeAlgorithm: 0
textureFormat: -1
textureCompression: 1
compressionQuality: 50
crunchedCompression: 0
allowsAlphaSplitting: 0
overridden: 0
ignorePlatformSupport: 0
androidETC2FallbackOverride: 0
forceMaximumCompressionQuality_BC6H_BC7: 0
spriteSheet:
serializedVersion: 2
sprites:
- serializedVersion: 2
name: how_to_play_goal0008_0
rect:
serializedVersion: 2
x: 0
y: 0
width: 1080
height: 1920
alignment: 0
pivot: {x: 0, y: 0}
border: {x: 0, y: 0, z: 0, w: 0}
customData:
outline: []
physicsShape: []
tessellationDetail: -1
bones: []
spriteID: a14b1c79d9b8099d0800000000000000
internalID: -2769560261860674534
vertices: []
indices:
edges: []
weights: []
outline: []
customData:
physicsShape: []
bones: []
spriteID:
internalID: 0
vertices: []
indices:
edges: []
weights: []
secondaryTextures: []
spriteCustomMetadata:
entries: []
nameFileIdTable:
how_to_play_goal0008_0: -2769560261860674534
mipmapLimitGroupName:
pSDRemoveMatte: 0
userData:
assetBundleName:
assetBundleVariant:
Binary file not shown.

After

Width:  |  Height:  |  Size: 62 KiB

@@ -0,0 +1,156 @@
fileFormatVersion: 2
guid: 0380b9106f20e364f9829e45849b93b5
TextureImporter:
internalIDToNameTable:
- first:
213: 337469173700556176
second: how_to_play_goal0009_0
externalObjects: {}
serializedVersion: 13
mipmaps:
mipMapMode: 0
enableMipMap: 0
sRGBTexture: 1
linearTexture: 0
fadeOut: 0
borderMipMap: 0
mipMapsPreserveCoverage: 0
alphaTestReferenceValue: 0.5
mipMapFadeDistanceStart: 1
mipMapFadeDistanceEnd: 3
bumpmap:
convertToNormalMap: 0
externalNormalMap: 0
heightScale: 0.25
normalMapFilter: 0
flipGreenChannel: 0
isReadable: 0
streamingMipmaps: 0
streamingMipmapsPriority: 0
vTOnly: 0
ignoreMipmapLimit: 0
grayScaleToAlpha: 0
generateCubemap: 6
cubemapConvolution: 0
seamlessCubemap: 0
textureFormat: 1
maxTextureSize: 2048
textureSettings:
serializedVersion: 2
filterMode: 1
aniso: 1
mipBias: 0
wrapU: 1
wrapV: 1
wrapW: 1
nPOTScale: 0
lightmap: 0
compressionQuality: 50
spriteMode: 2
spriteExtrude: 1
spriteMeshType: 1
alignment: 0
spritePivot: {x: 0.5, y: 0.5}
spritePixelsToUnits: 100
spriteBorder: {x: 0, y: 0, z: 0, w: 0}
spriteGenerateFallbackPhysicsShape: 1
alphaUsage: 1
alphaIsTransparency: 1
spriteTessellationDetail: -1
textureType: 8
textureShape: 1
singleChannelComponent: 0
flipbookRows: 1
flipbookColumns: 1
maxTextureSizeSet: 0
compressionQualitySet: 0
textureFormatSet: 0
ignorePngGamma: 0
applyGammaDecoding: 0
swizzle: 50462976
cookieLightType: 0
platformSettings:
- serializedVersion: 4
buildTarget: DefaultTexturePlatform
maxTextureSize: 1024
resizeAlgorithm: 0
textureFormat: -1
textureCompression: 1
compressionQuality: 50
crunchedCompression: 1
allowsAlphaSplitting: 0
overridden: 0
ignorePlatformSupport: 0
androidETC2FallbackOverride: 0
forceMaximumCompressionQuality_BC6H_BC7: 0
- serializedVersion: 4
buildTarget: Standalone
maxTextureSize: 2048
resizeAlgorithm: 0
textureFormat: -1
textureCompression: 1
compressionQuality: 50
crunchedCompression: 0
allowsAlphaSplitting: 0
overridden: 0
ignorePlatformSupport: 0
androidETC2FallbackOverride: 0
forceMaximumCompressionQuality_BC6H_BC7: 0
- serializedVersion: 4
buildTarget: Android
maxTextureSize: 2048
resizeAlgorithm: 0
textureFormat: -1
textureCompression: 1
compressionQuality: 50
crunchedCompression: 0
allowsAlphaSplitting: 0
overridden: 0
ignorePlatformSupport: 0
androidETC2FallbackOverride: 0
forceMaximumCompressionQuality_BC6H_BC7: 0
spriteSheet:
serializedVersion: 2
sprites:
- serializedVersion: 2
name: how_to_play_goal0009_0
rect:
serializedVersion: 2
x: 0
y: 0
width: 1080
height: 1920
alignment: 0
pivot: {x: 0, y: 0}
border: {x: 0, y: 0, z: 0, w: 0}
customData:
outline: []
physicsShape: []
tessellationDetail: -1
bones: []
spriteID: 095f01dec6eeea400800000000000000
internalID: 337469173700556176
vertices: []
indices:
edges: []
weights: []
outline: []
customData:
physicsShape: []
bones: []
spriteID:
internalID: 0
vertices: []
indices:
edges: []
weights: []
secondaryTextures: []
spriteCustomMetadata:
entries: []
nameFileIdTable:
how_to_play_goal0009_0: 337469173700556176
mipmapLimitGroupName:
pSDRemoveMatte: 0
userData:
assetBundleName:
assetBundleVariant:
Binary file not shown.

After

Width:  |  Height:  |  Size: 57 KiB

@@ -0,0 +1,156 @@
fileFormatVersion: 2
guid: 2889f9b33b3507d4596f7460716eb88a
TextureImporter:
internalIDToNameTable:
- first:
213: -1893092822091598629
second: how_to_play_goal0010_0
externalObjects: {}
serializedVersion: 13
mipmaps:
mipMapMode: 0
enableMipMap: 0
sRGBTexture: 1
linearTexture: 0
fadeOut: 0
borderMipMap: 0
mipMapsPreserveCoverage: 0
alphaTestReferenceValue: 0.5
mipMapFadeDistanceStart: 1
mipMapFadeDistanceEnd: 3
bumpmap:
convertToNormalMap: 0
externalNormalMap: 0
heightScale: 0.25
normalMapFilter: 0
flipGreenChannel: 0
isReadable: 0
streamingMipmaps: 0
streamingMipmapsPriority: 0
vTOnly: 0
ignoreMipmapLimit: 0
grayScaleToAlpha: 0
generateCubemap: 6
cubemapConvolution: 0
seamlessCubemap: 0
textureFormat: 1
maxTextureSize: 2048
textureSettings:
serializedVersion: 2
filterMode: 1
aniso: 1
mipBias: 0
wrapU: 1
wrapV: 1
wrapW: 1
nPOTScale: 0
lightmap: 0
compressionQuality: 50
spriteMode: 2
spriteExtrude: 1
spriteMeshType: 1
alignment: 0
spritePivot: {x: 0.5, y: 0.5}
spritePixelsToUnits: 100
spriteBorder: {x: 0, y: 0, z: 0, w: 0}
spriteGenerateFallbackPhysicsShape: 1
alphaUsage: 1
alphaIsTransparency: 1
spriteTessellationDetail: -1
textureType: 8
textureShape: 1
singleChannelComponent: 0
flipbookRows: 1
flipbookColumns: 1
maxTextureSizeSet: 0
compressionQualitySet: 0
textureFormatSet: 0
ignorePngGamma: 0
applyGammaDecoding: 0
swizzle: 50462976
cookieLightType: 0
platformSettings:
- serializedVersion: 4
buildTarget: DefaultTexturePlatform
maxTextureSize: 1024
resizeAlgorithm: 0
textureFormat: -1
textureCompression: 1
compressionQuality: 50
crunchedCompression: 1
allowsAlphaSplitting: 0
overridden: 0
ignorePlatformSupport: 0
androidETC2FallbackOverride: 0
forceMaximumCompressionQuality_BC6H_BC7: 0
- serializedVersion: 4
buildTarget: Standalone
maxTextureSize: 2048
resizeAlgorithm: 0
textureFormat: -1
textureCompression: 1
compressionQuality: 50
crunchedCompression: 0
allowsAlphaSplitting: 0
overridden: 0
ignorePlatformSupport: 0
androidETC2FallbackOverride: 0
forceMaximumCompressionQuality_BC6H_BC7: 0
- serializedVersion: 4
buildTarget: Android
maxTextureSize: 2048
resizeAlgorithm: 0
textureFormat: -1
textureCompression: 1
compressionQuality: 50
crunchedCompression: 0
allowsAlphaSplitting: 0
overridden: 0
ignorePlatformSupport: 0
androidETC2FallbackOverride: 0
forceMaximumCompressionQuality_BC6H_BC7: 0
spriteSheet:
serializedVersion: 2
sprites:
- serializedVersion: 2
name: how_to_play_goal0010_0
rect:
serializedVersion: 2
x: 0
y: 0
width: 1080
height: 1920
alignment: 0
pivot: {x: 0, y: 0}
border: {x: 0, y: 0, z: 0, w: 0}
customData:
outline: []
physicsShape: []
tessellationDetail: -1
bones: []
spriteID: bd4736cbb126ab5e0800000000000000
internalID: -1893092822091598629
vertices: []
indices:
edges: []
weights: []
outline: []
customData:
physicsShape: []
bones: []
spriteID:
internalID: 0
vertices: []
indices:
edges: []
weights: []
secondaryTextures: []
spriteCustomMetadata:
entries: []
nameFileIdTable:
how_to_play_goal0010_0: -1893092822091598629
mipmapLimitGroupName:
pSDRemoveMatte: 0
userData:
assetBundleName:
assetBundleVariant:
Binary file not shown.

After

Width:  |  Height:  |  Size: 52 KiB

@@ -0,0 +1,156 @@
fileFormatVersion: 2
guid: dd8d5e7fd43d915419a9bc4c4a13c87f
TextureImporter:
internalIDToNameTable:
- first:
213: -3779762386179194896
second: how_to_play_goal0011_0
externalObjects: {}
serializedVersion: 13
mipmaps:
mipMapMode: 0
enableMipMap: 0
sRGBTexture: 1
linearTexture: 0
fadeOut: 0
borderMipMap: 0
mipMapsPreserveCoverage: 0
alphaTestReferenceValue: 0.5
mipMapFadeDistanceStart: 1
mipMapFadeDistanceEnd: 3
bumpmap:
convertToNormalMap: 0
externalNormalMap: 0
heightScale: 0.25
normalMapFilter: 0
flipGreenChannel: 0
isReadable: 0
streamingMipmaps: 0
streamingMipmapsPriority: 0
vTOnly: 0
ignoreMipmapLimit: 0
grayScaleToAlpha: 0
generateCubemap: 6
cubemapConvolution: 0
seamlessCubemap: 0
textureFormat: 1
maxTextureSize: 2048
textureSettings:
serializedVersion: 2
filterMode: 1
aniso: 1
mipBias: 0
wrapU: 1
wrapV: 1
wrapW: 1
nPOTScale: 0
lightmap: 0
compressionQuality: 50
spriteMode: 2
spriteExtrude: 1
spriteMeshType: 1
alignment: 0
spritePivot: {x: 0.5, y: 0.5}
spritePixelsToUnits: 100
spriteBorder: {x: 0, y: 0, z: 0, w: 0}
spriteGenerateFallbackPhysicsShape: 1
alphaUsage: 1
alphaIsTransparency: 1
spriteTessellationDetail: -1
textureType: 8
textureShape: 1
singleChannelComponent: 0
flipbookRows: 1
flipbookColumns: 1
maxTextureSizeSet: 0
compressionQualitySet: 0
textureFormatSet: 0
ignorePngGamma: 0
applyGammaDecoding: 0
swizzle: 50462976
cookieLightType: 0
platformSettings:
- serializedVersion: 4
buildTarget: DefaultTexturePlatform
maxTextureSize: 1024
resizeAlgorithm: 0
textureFormat: -1
textureCompression: 1
compressionQuality: 50
crunchedCompression: 1
allowsAlphaSplitting: 0
overridden: 0
ignorePlatformSupport: 0
androidETC2FallbackOverride: 0
forceMaximumCompressionQuality_BC6H_BC7: 0
- serializedVersion: 4
buildTarget: Standalone
maxTextureSize: 2048
resizeAlgorithm: 0
textureFormat: -1
textureCompression: 1
compressionQuality: 50
crunchedCompression: 0
allowsAlphaSplitting: 0
overridden: 0
ignorePlatformSupport: 0
androidETC2FallbackOverride: 0
forceMaximumCompressionQuality_BC6H_BC7: 0
- serializedVersion: 4
buildTarget: Android
maxTextureSize: 2048
resizeAlgorithm: 0
textureFormat: -1
textureCompression: 1
compressionQuality: 50
crunchedCompression: 0
allowsAlphaSplitting: 0
overridden: 0
ignorePlatformSupport: 0
androidETC2FallbackOverride: 0
forceMaximumCompressionQuality_BC6H_BC7: 0
spriteSheet:
serializedVersion: 2
sprites:
- serializedVersion: 2
name: how_to_play_goal0011_0
rect:
serializedVersion: 2
x: 0
y: 0
width: 1080
height: 1920
alignment: 0
pivot: {x: 0, y: 0}
border: {x: 0, y: 0, z: 0, w: 0}
customData:
outline: []
physicsShape: []
tessellationDetail: -1
bones: []
spriteID: 0fff764c2269b8bc0800000000000000
internalID: -3779762386179194896
vertices: []
indices:
edges: []
weights: []
outline: []
customData:
physicsShape: []
bones: []
spriteID:
internalID: 0
vertices: []
indices:
edges: []
weights: []
secondaryTextures: []
spriteCustomMetadata:
entries: []
nameFileIdTable:
how_to_play_goal0011_0: -3779762386179194896
mipmapLimitGroupName:
pSDRemoveMatte: 0
userData:
assetBundleName:
assetBundleVariant:
Binary file not shown.

After

Width:  |  Height:  |  Size: 50 KiB

@@ -0,0 +1,156 @@
fileFormatVersion: 2
guid: 58f8fdb8db035fe42925165db312de6f
TextureImporter:
internalIDToNameTable:
- first:
213: 1568047047368444430
second: how_to_play_goal0012_0
externalObjects: {}
serializedVersion: 13
mipmaps:
mipMapMode: 0
enableMipMap: 0
sRGBTexture: 1
linearTexture: 0
fadeOut: 0
borderMipMap: 0
mipMapsPreserveCoverage: 0
alphaTestReferenceValue: 0.5
mipMapFadeDistanceStart: 1
mipMapFadeDistanceEnd: 3
bumpmap:
convertToNormalMap: 0
externalNormalMap: 0
heightScale: 0.25
normalMapFilter: 0
flipGreenChannel: 0
isReadable: 0
streamingMipmaps: 0
streamingMipmapsPriority: 0
vTOnly: 0
ignoreMipmapLimit: 0
grayScaleToAlpha: 0
generateCubemap: 6
cubemapConvolution: 0
seamlessCubemap: 0
textureFormat: 1
maxTextureSize: 2048
textureSettings:
serializedVersion: 2
filterMode: 1
aniso: 1
mipBias: 0
wrapU: 1
wrapV: 1
wrapW: 1
nPOTScale: 0
lightmap: 0
compressionQuality: 50
spriteMode: 2
spriteExtrude: 1
spriteMeshType: 1
alignment: 0
spritePivot: {x: 0.5, y: 0.5}
spritePixelsToUnits: 100
spriteBorder: {x: 0, y: 0, z: 0, w: 0}
spriteGenerateFallbackPhysicsShape: 1
alphaUsage: 1
alphaIsTransparency: 1
spriteTessellationDetail: -1
textureType: 8
textureShape: 1
singleChannelComponent: 0
flipbookRows: 1
flipbookColumns: 1
maxTextureSizeSet: 0
compressionQualitySet: 0
textureFormatSet: 0
ignorePngGamma: 0
applyGammaDecoding: 0
swizzle: 50462976
cookieLightType: 0
platformSettings:
- serializedVersion: 4
buildTarget: DefaultTexturePlatform
maxTextureSize: 1024
resizeAlgorithm: 0
textureFormat: -1
textureCompression: 1
compressionQuality: 50
crunchedCompression: 1
allowsAlphaSplitting: 0
overridden: 0
ignorePlatformSupport: 0
androidETC2FallbackOverride: 0
forceMaximumCompressionQuality_BC6H_BC7: 0
- serializedVersion: 4
buildTarget: Standalone
maxTextureSize: 2048
resizeAlgorithm: 0
textureFormat: -1
textureCompression: 1
compressionQuality: 50
crunchedCompression: 0
allowsAlphaSplitting: 0
overridden: 0
ignorePlatformSupport: 0
androidETC2FallbackOverride: 0
forceMaximumCompressionQuality_BC6H_BC7: 0
- serializedVersion: 4
buildTarget: Android
maxTextureSize: 2048
resizeAlgorithm: 0
textureFormat: -1
textureCompression: 1
compressionQuality: 50
crunchedCompression: 0
allowsAlphaSplitting: 0
overridden: 0
ignorePlatformSupport: 0
androidETC2FallbackOverride: 0
forceMaximumCompressionQuality_BC6H_BC7: 0
spriteSheet:
serializedVersion: 2
sprites:
- serializedVersion: 2
name: how_to_play_goal0012_0
rect:
serializedVersion: 2
x: 0
y: 0
width: 1080
height: 1920
alignment: 0
pivot: {x: 0, y: 0}
border: {x: 0, y: 0, z: 0, w: 0}
customData:
outline: []
physicsShape: []
tessellationDetail: -1
bones: []
spriteID: e0a0f715b72d2c510800000000000000
internalID: 1568047047368444430
vertices: []
indices:
edges: []
weights: []
outline: []
customData:
physicsShape: []
bones: []
spriteID:
internalID: 0
vertices: []
indices:
edges: []
weights: []
secondaryTextures: []
spriteCustomMetadata:
entries: []
nameFileIdTable:
how_to_play_goal0012_0: 1568047047368444430
mipmapLimitGroupName:
pSDRemoveMatte: 0
userData:
assetBundleName:
assetBundleVariant:
Binary file not shown.

After

Width:  |  Height:  |  Size: 50 KiB

@@ -0,0 +1,156 @@
fileFormatVersion: 2
guid: 571163594414f9940a46e54e3a28ba3e
TextureImporter:
internalIDToNameTable:
- first:
213: 3341768276131303601
second: how_to_play_goal0013_0
externalObjects: {}
serializedVersion: 13
mipmaps:
mipMapMode: 0
enableMipMap: 0
sRGBTexture: 1
linearTexture: 0
fadeOut: 0
borderMipMap: 0
mipMapsPreserveCoverage: 0
alphaTestReferenceValue: 0.5
mipMapFadeDistanceStart: 1
mipMapFadeDistanceEnd: 3
bumpmap:
convertToNormalMap: 0
externalNormalMap: 0
heightScale: 0.25
normalMapFilter: 0
flipGreenChannel: 0
isReadable: 0
streamingMipmaps: 0
streamingMipmapsPriority: 0
vTOnly: 0
ignoreMipmapLimit: 0
grayScaleToAlpha: 0
generateCubemap: 6
cubemapConvolution: 0
seamlessCubemap: 0
textureFormat: 1
maxTextureSize: 2048
textureSettings:
serializedVersion: 2
filterMode: 1
aniso: 1
mipBias: 0
wrapU: 1
wrapV: 1
wrapW: 1
nPOTScale: 0
lightmap: 0
compressionQuality: 50
spriteMode: 2
spriteExtrude: 1
spriteMeshType: 1
alignment: 0
spritePivot: {x: 0.5, y: 0.5}
spritePixelsToUnits: 100
spriteBorder: {x: 0, y: 0, z: 0, w: 0}
spriteGenerateFallbackPhysicsShape: 1
alphaUsage: 1
alphaIsTransparency: 1
spriteTessellationDetail: -1
textureType: 8
textureShape: 1
singleChannelComponent: 0
flipbookRows: 1
flipbookColumns: 1
maxTextureSizeSet: 0
compressionQualitySet: 0
textureFormatSet: 0
ignorePngGamma: 0
applyGammaDecoding: 0
swizzle: 50462976
cookieLightType: 0
platformSettings:
- serializedVersion: 4
buildTarget: DefaultTexturePlatform
maxTextureSize: 1024
resizeAlgorithm: 0
textureFormat: -1
textureCompression: 1
compressionQuality: 50
crunchedCompression: 1
allowsAlphaSplitting: 0
overridden: 0
ignorePlatformSupport: 0
androidETC2FallbackOverride: 0
forceMaximumCompressionQuality_BC6H_BC7: 0
- serializedVersion: 4
buildTarget: Standalone
maxTextureSize: 2048
resizeAlgorithm: 0
textureFormat: -1
textureCompression: 1
compressionQuality: 50
crunchedCompression: 0
allowsAlphaSplitting: 0
overridden: 0
ignorePlatformSupport: 0
androidETC2FallbackOverride: 0
forceMaximumCompressionQuality_BC6H_BC7: 0
- serializedVersion: 4
buildTarget: Android
maxTextureSize: 2048
resizeAlgorithm: 0
textureFormat: -1
textureCompression: 1
compressionQuality: 50
crunchedCompression: 0
allowsAlphaSplitting: 0
overridden: 0
ignorePlatformSupport: 0
androidETC2FallbackOverride: 0
forceMaximumCompressionQuality_BC6H_BC7: 0
spriteSheet:
serializedVersion: 2
sprites:
- serializedVersion: 2
name: how_to_play_goal0013_0
rect:
serializedVersion: 2
x: 0
y: 0
width: 1080
height: 1920
alignment: 0
pivot: {x: 0, y: 0}
border: {x: 0, y: 0, z: 0, w: 0}
customData:
outline: []
physicsShape: []
tessellationDetail: -1
bones: []
spriteID: 1b0d97caa88506e20800000000000000
internalID: 3341768276131303601
vertices: []
indices:
edges: []
weights: []
outline: []
customData:
physicsShape: []
bones: []
spriteID:
internalID: 0
vertices: []
indices:
edges: []
weights: []
secondaryTextures: []
spriteCustomMetadata:
entries: []
nameFileIdTable:
how_to_play_goal0013_0: 3341768276131303601
mipmapLimitGroupName:
pSDRemoveMatte: 0
userData:
assetBundleName:
assetBundleVariant:
Binary file not shown.

After

Width:  |  Height:  |  Size: 50 KiB

@@ -0,0 +1,156 @@
fileFormatVersion: 2
guid: c3ea11aecfb35934fbd6ebfd75367b7f
TextureImporter:
internalIDToNameTable:
- first:
213: -3274699238553858469
second: how_to_play_goal0014_0
externalObjects: {}
serializedVersion: 13
mipmaps:
mipMapMode: 0
enableMipMap: 0
sRGBTexture: 1
linearTexture: 0
fadeOut: 0
borderMipMap: 0
mipMapsPreserveCoverage: 0
alphaTestReferenceValue: 0.5
mipMapFadeDistanceStart: 1
mipMapFadeDistanceEnd: 3
bumpmap:
convertToNormalMap: 0
externalNormalMap: 0
heightScale: 0.25
normalMapFilter: 0
flipGreenChannel: 0
isReadable: 0
streamingMipmaps: 0
streamingMipmapsPriority: 0
vTOnly: 0
ignoreMipmapLimit: 0
grayScaleToAlpha: 0
generateCubemap: 6
cubemapConvolution: 0
seamlessCubemap: 0
textureFormat: 1
maxTextureSize: 2048
textureSettings:
serializedVersion: 2
filterMode: 1
aniso: 1
mipBias: 0
wrapU: 1
wrapV: 1
wrapW: 1
nPOTScale: 0
lightmap: 0
compressionQuality: 50
spriteMode: 2
spriteExtrude: 1
spriteMeshType: 1
alignment: 0
spritePivot: {x: 0.5, y: 0.5}
spritePixelsToUnits: 100
spriteBorder: {x: 0, y: 0, z: 0, w: 0}
spriteGenerateFallbackPhysicsShape: 1
alphaUsage: 1
alphaIsTransparency: 1
spriteTessellationDetail: -1
textureType: 8
textureShape: 1
singleChannelComponent: 0
flipbookRows: 1
flipbookColumns: 1
maxTextureSizeSet: 0
compressionQualitySet: 0
textureFormatSet: 0
ignorePngGamma: 0
applyGammaDecoding: 0
swizzle: 50462976
cookieLightType: 0
platformSettings:
- serializedVersion: 4
buildTarget: DefaultTexturePlatform
maxTextureSize: 1024
resizeAlgorithm: 0
textureFormat: -1
textureCompression: 1
compressionQuality: 50
crunchedCompression: 1
allowsAlphaSplitting: 0
overridden: 0
ignorePlatformSupport: 0
androidETC2FallbackOverride: 0
forceMaximumCompressionQuality_BC6H_BC7: 0
- serializedVersion: 4
buildTarget: Standalone
maxTextureSize: 2048
resizeAlgorithm: 0
textureFormat: -1
textureCompression: 1
compressionQuality: 50
crunchedCompression: 0
allowsAlphaSplitting: 0
overridden: 0
ignorePlatformSupport: 0
androidETC2FallbackOverride: 0
forceMaximumCompressionQuality_BC6H_BC7: 0
- serializedVersion: 4
buildTarget: Android
maxTextureSize: 2048
resizeAlgorithm: 0
textureFormat: -1
textureCompression: 1
compressionQuality: 50
crunchedCompression: 0
allowsAlphaSplitting: 0
overridden: 0
ignorePlatformSupport: 0
androidETC2FallbackOverride: 0
forceMaximumCompressionQuality_BC6H_BC7: 0
spriteSheet:
serializedVersion: 2
sprites:
- serializedVersion: 2
name: how_to_play_goal0014_0
rect:
serializedVersion: 2
x: 0
y: 0
width: 1080
height: 1920
alignment: 0
pivot: {x: 0, y: 0}
border: {x: 0, y: 0, z: 0, w: 0}
customData:
outline: []
physicsShape: []
tessellationDetail: -1
bones: []
spriteID: b5e41c3846eed82d0800000000000000
internalID: -3274699238553858469
vertices: []
indices:
edges: []
weights: []
outline: []
customData:
physicsShape: []
bones: []
spriteID:
internalID: 0
vertices: []
indices:
edges: []
weights: []
secondaryTextures: []
spriteCustomMetadata:
entries: []
nameFileIdTable:
how_to_play_goal0014_0: -3274699238553858469
mipmapLimitGroupName:
pSDRemoveMatte: 0
userData:
assetBundleName:
assetBundleVariant:
Binary file not shown.

After

Width:  |  Height:  |  Size: 49 KiB

@@ -0,0 +1,156 @@
fileFormatVersion: 2
guid: cbb0ccfaf845bcf4b9b318e7e17b2386
TextureImporter:
internalIDToNameTable:
- first:
213: -2904124417626424539
second: how_to_play_goal0015_0
externalObjects: {}
serializedVersion: 13
mipmaps:
mipMapMode: 0
enableMipMap: 0
sRGBTexture: 1
linearTexture: 0
fadeOut: 0
borderMipMap: 0
mipMapsPreserveCoverage: 0
alphaTestReferenceValue: 0.5
mipMapFadeDistanceStart: 1
mipMapFadeDistanceEnd: 3
bumpmap:
convertToNormalMap: 0
externalNormalMap: 0
heightScale: 0.25
normalMapFilter: 0
flipGreenChannel: 0
isReadable: 0
streamingMipmaps: 0
streamingMipmapsPriority: 0
vTOnly: 0
ignoreMipmapLimit: 0
grayScaleToAlpha: 0
generateCubemap: 6
cubemapConvolution: 0
seamlessCubemap: 0
textureFormat: 1
maxTextureSize: 2048
textureSettings:
serializedVersion: 2
filterMode: 1
aniso: 1
mipBias: 0
wrapU: 1
wrapV: 1
wrapW: 1
nPOTScale: 0
lightmap: 0
compressionQuality: 50
spriteMode: 2
spriteExtrude: 1
spriteMeshType: 1
alignment: 0
spritePivot: {x: 0.5, y: 0.5}
spritePixelsToUnits: 100
spriteBorder: {x: 0, y: 0, z: 0, w: 0}
spriteGenerateFallbackPhysicsShape: 1
alphaUsage: 1
alphaIsTransparency: 1
spriteTessellationDetail: -1
textureType: 8
textureShape: 1
singleChannelComponent: 0
flipbookRows: 1
flipbookColumns: 1
maxTextureSizeSet: 0
compressionQualitySet: 0
textureFormatSet: 0
ignorePngGamma: 0
applyGammaDecoding: 0
swizzle: 50462976
cookieLightType: 0
platformSettings:
- serializedVersion: 4
buildTarget: DefaultTexturePlatform
maxTextureSize: 1024
resizeAlgorithm: 0
textureFormat: -1
textureCompression: 1
compressionQuality: 50
crunchedCompression: 1
allowsAlphaSplitting: 0
overridden: 0
ignorePlatformSupport: 0
androidETC2FallbackOverride: 0
forceMaximumCompressionQuality_BC6H_BC7: 0
- serializedVersion: 4
buildTarget: Standalone
maxTextureSize: 2048
resizeAlgorithm: 0
textureFormat: -1
textureCompression: 1
compressionQuality: 50
crunchedCompression: 0
allowsAlphaSplitting: 0
overridden: 0
ignorePlatformSupport: 0
androidETC2FallbackOverride: 0
forceMaximumCompressionQuality_BC6H_BC7: 0
- serializedVersion: 4
buildTarget: Android
maxTextureSize: 2048
resizeAlgorithm: 0
textureFormat: -1
textureCompression: 1
compressionQuality: 50
crunchedCompression: 0
allowsAlphaSplitting: 0
overridden: 0
ignorePlatformSupport: 0
androidETC2FallbackOverride: 0
forceMaximumCompressionQuality_BC6H_BC7: 0
spriteSheet:
serializedVersion: 2
sprites:
- serializedVersion: 2
name: how_to_play_goal0015_0
rect:
serializedVersion: 2
x: 0
y: 0
width: 1080
height: 1920
alignment: 0
pivot: {x: 0, y: 0}
border: {x: 0, y: 0, z: 0, w: 0}
customData:
outline: []
physicsShape: []
tessellationDetail: -1
bones: []
spriteID: 52bb6d79a3a72b7d0800000000000000
internalID: -2904124417626424539
vertices: []
indices:
edges: []
weights: []
outline: []
customData:
physicsShape: []
bones: []
spriteID:
internalID: 0
vertices: []
indices:
edges: []
weights: []
secondaryTextures: []
spriteCustomMetadata:
entries: []
nameFileIdTable:
how_to_play_goal0015_0: -2904124417626424539
mipmapLimitGroupName:
pSDRemoveMatte: 0
userData:
assetBundleName:
assetBundleVariant:
Binary file not shown.

After

Width:  |  Height:  |  Size: 49 KiB

@@ -0,0 +1,156 @@
fileFormatVersion: 2
guid: 648f5791cf82b074eb22242756e7a84e
TextureImporter:
internalIDToNameTable:
- first:
213: 7807152604696158922
second: how_to_play_goal0016_0
externalObjects: {}
serializedVersion: 13
mipmaps:
mipMapMode: 0
enableMipMap: 0
sRGBTexture: 1
linearTexture: 0
fadeOut: 0
borderMipMap: 0
mipMapsPreserveCoverage: 0
alphaTestReferenceValue: 0.5
mipMapFadeDistanceStart: 1
mipMapFadeDistanceEnd: 3
bumpmap:
convertToNormalMap: 0
externalNormalMap: 0
heightScale: 0.25
normalMapFilter: 0
flipGreenChannel: 0
isReadable: 0
streamingMipmaps: 0
streamingMipmapsPriority: 0
vTOnly: 0
ignoreMipmapLimit: 0
grayScaleToAlpha: 0
generateCubemap: 6
cubemapConvolution: 0
seamlessCubemap: 0
textureFormat: 1
maxTextureSize: 2048
textureSettings:
serializedVersion: 2
filterMode: 1
aniso: 1
mipBias: 0
wrapU: 1
wrapV: 1
wrapW: 1
nPOTScale: 0
lightmap: 0
compressionQuality: 50
spriteMode: 2
spriteExtrude: 1
spriteMeshType: 1
alignment: 0
spritePivot: {x: 0.5, y: 0.5}
spritePixelsToUnits: 100
spriteBorder: {x: 0, y: 0, z: 0, w: 0}
spriteGenerateFallbackPhysicsShape: 1
alphaUsage: 1
alphaIsTransparency: 1
spriteTessellationDetail: -1
textureType: 8
textureShape: 1
singleChannelComponent: 0
flipbookRows: 1
flipbookColumns: 1
maxTextureSizeSet: 0
compressionQualitySet: 0
textureFormatSet: 0
ignorePngGamma: 0
applyGammaDecoding: 0
swizzle: 50462976
cookieLightType: 0
platformSettings:
- serializedVersion: 4
buildTarget: DefaultTexturePlatform
maxTextureSize: 1024
resizeAlgorithm: 0
textureFormat: -1
textureCompression: 1
compressionQuality: 50
crunchedCompression: 1
allowsAlphaSplitting: 0
overridden: 0
ignorePlatformSupport: 0
androidETC2FallbackOverride: 0
forceMaximumCompressionQuality_BC6H_BC7: 0
- serializedVersion: 4
buildTarget: Standalone
maxTextureSize: 2048
resizeAlgorithm: 0
textureFormat: -1
textureCompression: 1
compressionQuality: 50
crunchedCompression: 0
allowsAlphaSplitting: 0
overridden: 0
ignorePlatformSupport: 0
androidETC2FallbackOverride: 0
forceMaximumCompressionQuality_BC6H_BC7: 0
- serializedVersion: 4
buildTarget: Android
maxTextureSize: 2048
resizeAlgorithm: 0
textureFormat: -1
textureCompression: 1
compressionQuality: 50
crunchedCompression: 0
allowsAlphaSplitting: 0
overridden: 0
ignorePlatformSupport: 0
androidETC2FallbackOverride: 0
forceMaximumCompressionQuality_BC6H_BC7: 0
spriteSheet:
serializedVersion: 2
sprites:
- serializedVersion: 2
name: how_to_play_goal0016_0
rect:
serializedVersion: 2
x: 0
y: 0
width: 1080
height: 1920
alignment: 0
pivot: {x: 0, y: 0}
border: {x: 0, y: 0, z: 0, w: 0}
customData:
outline: []
physicsShape: []
tessellationDetail: -1
bones: []
spriteID: ac22e2e0ee3985c60800000000000000
internalID: 7807152604696158922
vertices: []
indices:
edges: []
weights: []
outline: []
customData:
physicsShape: []
bones: []
spriteID:
internalID: 0
vertices: []
indices:
edges: []
weights: []
secondaryTextures: []
spriteCustomMetadata:
entries: []
nameFileIdTable:
how_to_play_goal0016_0: 7807152604696158922
mipmapLimitGroupName:
pSDRemoveMatte: 0
userData:
assetBundleName:
assetBundleVariant:
Binary file not shown.

After

Width:  |  Height:  |  Size: 49 KiB

@@ -0,0 +1,156 @@
fileFormatVersion: 2
guid: ddc6d2f24c0fc464089d070137d69153
TextureImporter:
internalIDToNameTable:
- first:
213: -7436839558645834474
second: how_to_play_goal0017_0
externalObjects: {}
serializedVersion: 13
mipmaps:
mipMapMode: 0
enableMipMap: 0
sRGBTexture: 1
linearTexture: 0
fadeOut: 0
borderMipMap: 0
mipMapsPreserveCoverage: 0
alphaTestReferenceValue: 0.5
mipMapFadeDistanceStart: 1
mipMapFadeDistanceEnd: 3
bumpmap:
convertToNormalMap: 0
externalNormalMap: 0
heightScale: 0.25
normalMapFilter: 0
flipGreenChannel: 0
isReadable: 0
streamingMipmaps: 0
streamingMipmapsPriority: 0
vTOnly: 0
ignoreMipmapLimit: 0
grayScaleToAlpha: 0
generateCubemap: 6
cubemapConvolution: 0
seamlessCubemap: 0
textureFormat: 1
maxTextureSize: 2048
textureSettings:
serializedVersion: 2
filterMode: 1
aniso: 1
mipBias: 0
wrapU: 1
wrapV: 1
wrapW: 1
nPOTScale: 0
lightmap: 0
compressionQuality: 50
spriteMode: 2
spriteExtrude: 1
spriteMeshType: 1
alignment: 0
spritePivot: {x: 0.5, y: 0.5}
spritePixelsToUnits: 100
spriteBorder: {x: 0, y: 0, z: 0, w: 0}
spriteGenerateFallbackPhysicsShape: 1
alphaUsage: 1
alphaIsTransparency: 1
spriteTessellationDetail: -1
textureType: 8
textureShape: 1
singleChannelComponent: 0
flipbookRows: 1
flipbookColumns: 1
maxTextureSizeSet: 0
compressionQualitySet: 0
textureFormatSet: 0
ignorePngGamma: 0
applyGammaDecoding: 0
swizzle: 50462976
cookieLightType: 0
platformSettings:
- serializedVersion: 4
buildTarget: DefaultTexturePlatform
maxTextureSize: 1024
resizeAlgorithm: 0
textureFormat: -1
textureCompression: 1
compressionQuality: 50
crunchedCompression: 1
allowsAlphaSplitting: 0
overridden: 0
ignorePlatformSupport: 0
androidETC2FallbackOverride: 0
forceMaximumCompressionQuality_BC6H_BC7: 0
- serializedVersion: 4
buildTarget: Standalone
maxTextureSize: 2048
resizeAlgorithm: 0
textureFormat: -1
textureCompression: 1
compressionQuality: 50
crunchedCompression: 0
allowsAlphaSplitting: 0
overridden: 0
ignorePlatformSupport: 0
androidETC2FallbackOverride: 0
forceMaximumCompressionQuality_BC6H_BC7: 0
- serializedVersion: 4
buildTarget: Android
maxTextureSize: 2048
resizeAlgorithm: 0
textureFormat: -1
textureCompression: 1
compressionQuality: 50
crunchedCompression: 0
allowsAlphaSplitting: 0
overridden: 0
ignorePlatformSupport: 0
androidETC2FallbackOverride: 0
forceMaximumCompressionQuality_BC6H_BC7: 0
spriteSheet:
serializedVersion: 2
sprites:
- serializedVersion: 2
name: how_to_play_goal0017_0
rect:
serializedVersion: 2
x: 0
y: 0
width: 1080
height: 1920
alignment: 0
pivot: {x: 0, y: 0}
border: {x: 0, y: 0, z: 0, w: 0}
customData:
outline: []
physicsShape: []
tessellationDetail: -1
bones: []
spriteID: 61d975fc2d90bc890800000000000000
internalID: -7436839558645834474
vertices: []
indices:
edges: []
weights: []
outline: []
customData:
physicsShape: []
bones: []
spriteID:
internalID: 0
vertices: []
indices:
edges: []
weights: []
secondaryTextures: []
spriteCustomMetadata:
entries: []
nameFileIdTable:
how_to_play_goal0017_0: -7436839558645834474
mipmapLimitGroupName:
pSDRemoveMatte: 0
userData:
assetBundleName:
assetBundleVariant:
Binary file not shown.

After

Width:  |  Height:  |  Size: 49 KiB

@@ -0,0 +1,156 @@
fileFormatVersion: 2
guid: c8cf7aae8cc60584989fd3e5780d9ada
TextureImporter:
internalIDToNameTable:
- first:
213: 8094720510830227213
second: how_to_play_goal0018_0
externalObjects: {}
serializedVersion: 13
mipmaps:
mipMapMode: 0
enableMipMap: 0
sRGBTexture: 1
linearTexture: 0
fadeOut: 0
borderMipMap: 0
mipMapsPreserveCoverage: 0
alphaTestReferenceValue: 0.5
mipMapFadeDistanceStart: 1
mipMapFadeDistanceEnd: 3
bumpmap:
convertToNormalMap: 0
externalNormalMap: 0
heightScale: 0.25
normalMapFilter: 0
flipGreenChannel: 0
isReadable: 0
streamingMipmaps: 0
streamingMipmapsPriority: 0
vTOnly: 0
ignoreMipmapLimit: 0
grayScaleToAlpha: 0
generateCubemap: 6
cubemapConvolution: 0
seamlessCubemap: 0
textureFormat: 1
maxTextureSize: 2048
textureSettings:
serializedVersion: 2
filterMode: 1
aniso: 1
mipBias: 0
wrapU: 1
wrapV: 1
wrapW: 1
nPOTScale: 0
lightmap: 0
compressionQuality: 50
spriteMode: 2
spriteExtrude: 1
spriteMeshType: 1
alignment: 0
spritePivot: {x: 0.5, y: 0.5}
spritePixelsToUnits: 100
spriteBorder: {x: 0, y: 0, z: 0, w: 0}
spriteGenerateFallbackPhysicsShape: 1
alphaUsage: 1
alphaIsTransparency: 1
spriteTessellationDetail: -1
textureType: 8
textureShape: 1
singleChannelComponent: 0
flipbookRows: 1
flipbookColumns: 1
maxTextureSizeSet: 0
compressionQualitySet: 0
textureFormatSet: 0
ignorePngGamma: 0
applyGammaDecoding: 0
swizzle: 50462976
cookieLightType: 0
platformSettings:
- serializedVersion: 4
buildTarget: DefaultTexturePlatform
maxTextureSize: 1024
resizeAlgorithm: 0
textureFormat: -1
textureCompression: 1
compressionQuality: 50
crunchedCompression: 1
allowsAlphaSplitting: 0
overridden: 0
ignorePlatformSupport: 0
androidETC2FallbackOverride: 0
forceMaximumCompressionQuality_BC6H_BC7: 0
- serializedVersion: 4
buildTarget: Standalone
maxTextureSize: 2048
resizeAlgorithm: 0
textureFormat: -1
textureCompression: 1
compressionQuality: 50
crunchedCompression: 0
allowsAlphaSplitting: 0
overridden: 0
ignorePlatformSupport: 0
androidETC2FallbackOverride: 0
forceMaximumCompressionQuality_BC6H_BC7: 0
- serializedVersion: 4
buildTarget: Android
maxTextureSize: 2048
resizeAlgorithm: 0
textureFormat: -1
textureCompression: 1
compressionQuality: 50
crunchedCompression: 0
allowsAlphaSplitting: 0
overridden: 0
ignorePlatformSupport: 0
androidETC2FallbackOverride: 0
forceMaximumCompressionQuality_BC6H_BC7: 0
spriteSheet:
serializedVersion: 2
sprites:
- serializedVersion: 2
name: how_to_play_goal0018_0
rect:
serializedVersion: 2
x: 0
y: 0
width: 1080
height: 1920
alignment: 0
pivot: {x: 0, y: 0}
border: {x: 0, y: 0, z: 0, w: 0}
customData:
outline: []
physicsShape: []
tessellationDetail: -1
bones: []
spriteID: d0faa1cba69365070800000000000000
internalID: 8094720510830227213
vertices: []
indices:
edges: []
weights: []
outline: []
customData:
physicsShape: []
bones: []
spriteID:
internalID: 0
vertices: []
indices:
edges: []
weights: []
secondaryTextures: []
spriteCustomMetadata:
entries: []
nameFileIdTable:
how_to_play_goal0018_0: 8094720510830227213
mipmapLimitGroupName:
pSDRemoveMatte: 0
userData:
assetBundleName:
assetBundleVariant:
Binary file not shown.

After

Width:  |  Height:  |  Size: 48 KiB

@@ -0,0 +1,156 @@
fileFormatVersion: 2
guid: de8f5c49b9afd07468509051e66d2cdf
TextureImporter:
internalIDToNameTable:
- first:
213: 7779922750506681629
second: how_to_play_goal0019_0
externalObjects: {}
serializedVersion: 13
mipmaps:
mipMapMode: 0
enableMipMap: 0
sRGBTexture: 1
linearTexture: 0
fadeOut: 0
borderMipMap: 0
mipMapsPreserveCoverage: 0
alphaTestReferenceValue: 0.5
mipMapFadeDistanceStart: 1
mipMapFadeDistanceEnd: 3
bumpmap:
convertToNormalMap: 0
externalNormalMap: 0
heightScale: 0.25
normalMapFilter: 0
flipGreenChannel: 0
isReadable: 0
streamingMipmaps: 0
streamingMipmapsPriority: 0
vTOnly: 0
ignoreMipmapLimit: 0
grayScaleToAlpha: 0
generateCubemap: 6
cubemapConvolution: 0
seamlessCubemap: 0
textureFormat: 1
maxTextureSize: 2048
textureSettings:
serializedVersion: 2
filterMode: 1
aniso: 1
mipBias: 0
wrapU: 1
wrapV: 1
wrapW: 1
nPOTScale: 0
lightmap: 0
compressionQuality: 50
spriteMode: 2
spriteExtrude: 1
spriteMeshType: 1
alignment: 0
spritePivot: {x: 0.5, y: 0.5}
spritePixelsToUnits: 100
spriteBorder: {x: 0, y: 0, z: 0, w: 0}
spriteGenerateFallbackPhysicsShape: 1
alphaUsage: 1
alphaIsTransparency: 1
spriteTessellationDetail: -1
textureType: 8
textureShape: 1
singleChannelComponent: 0
flipbookRows: 1
flipbookColumns: 1
maxTextureSizeSet: 0
compressionQualitySet: 0
textureFormatSet: 0
ignorePngGamma: 0
applyGammaDecoding: 0
swizzle: 50462976
cookieLightType: 0
platformSettings:
- serializedVersion: 4
buildTarget: DefaultTexturePlatform
maxTextureSize: 1024
resizeAlgorithm: 0
textureFormat: -1
textureCompression: 1
compressionQuality: 50
crunchedCompression: 1
allowsAlphaSplitting: 0
overridden: 0
ignorePlatformSupport: 0
androidETC2FallbackOverride: 0
forceMaximumCompressionQuality_BC6H_BC7: 0
- serializedVersion: 4
buildTarget: Standalone
maxTextureSize: 2048
resizeAlgorithm: 0
textureFormat: -1
textureCompression: 1
compressionQuality: 50
crunchedCompression: 0
allowsAlphaSplitting: 0
overridden: 0
ignorePlatformSupport: 0
androidETC2FallbackOverride: 0
forceMaximumCompressionQuality_BC6H_BC7: 0
- serializedVersion: 4
buildTarget: Android
maxTextureSize: 2048
resizeAlgorithm: 0
textureFormat: -1
textureCompression: 1
compressionQuality: 50
crunchedCompression: 0
allowsAlphaSplitting: 0
overridden: 0
ignorePlatformSupport: 0
androidETC2FallbackOverride: 0
forceMaximumCompressionQuality_BC6H_BC7: 0
spriteSheet:
serializedVersion: 2
sprites:
- serializedVersion: 2
name: how_to_play_goal0019_0
rect:
serializedVersion: 2
x: 0
y: 0
width: 1080
height: 1920
alignment: 0
pivot: {x: 0, y: 0}
border: {x: 0, y: 0, z: 0, w: 0}
customData:
outline: []
physicsShape: []
tessellationDetail: -1
bones: []
spriteID: d154ee39586d7fb60800000000000000
internalID: 7779922750506681629
vertices: []
indices:
edges: []
weights: []
outline: []
customData:
physicsShape: []
bones: []
spriteID:
internalID: 0
vertices: []
indices:
edges: []
weights: []
secondaryTextures: []
spriteCustomMetadata:
entries: []
nameFileIdTable:
how_to_play_goal0019_0: 7779922750506681629
mipmapLimitGroupName:
pSDRemoveMatte: 0
userData:
assetBundleName:
assetBundleVariant:
Binary file not shown.

After

Width:  |  Height:  |  Size: 48 KiB

@@ -0,0 +1,156 @@
fileFormatVersion: 2
guid: 4e82a0023f2925e4095a945e6cdd7561
TextureImporter:
internalIDToNameTable:
- first:
213: 3496087471285781191
second: how_to_play_goal0020_0
externalObjects: {}
serializedVersion: 13
mipmaps:
mipMapMode: 0
enableMipMap: 0
sRGBTexture: 1
linearTexture: 0
fadeOut: 0
borderMipMap: 0
mipMapsPreserveCoverage: 0
alphaTestReferenceValue: 0.5
mipMapFadeDistanceStart: 1
mipMapFadeDistanceEnd: 3
bumpmap:
convertToNormalMap: 0
externalNormalMap: 0
heightScale: 0.25
normalMapFilter: 0
flipGreenChannel: 0
isReadable: 0
streamingMipmaps: 0
streamingMipmapsPriority: 0
vTOnly: 0
ignoreMipmapLimit: 0
grayScaleToAlpha: 0
generateCubemap: 6
cubemapConvolution: 0
seamlessCubemap: 0
textureFormat: 1
maxTextureSize: 2048
textureSettings:
serializedVersion: 2
filterMode: 1
aniso: 1
mipBias: 0
wrapU: 1
wrapV: 1
wrapW: 1
nPOTScale: 0
lightmap: 0
compressionQuality: 50
spriteMode: 2
spriteExtrude: 1
spriteMeshType: 1
alignment: 0
spritePivot: {x: 0.5, y: 0.5}
spritePixelsToUnits: 100
spriteBorder: {x: 0, y: 0, z: 0, w: 0}
spriteGenerateFallbackPhysicsShape: 1
alphaUsage: 1
alphaIsTransparency: 1
spriteTessellationDetail: -1
textureType: 8
textureShape: 1
singleChannelComponent: 0
flipbookRows: 1
flipbookColumns: 1
maxTextureSizeSet: 0
compressionQualitySet: 0
textureFormatSet: 0
ignorePngGamma: 0
applyGammaDecoding: 0
swizzle: 50462976
cookieLightType: 0
platformSettings:
- serializedVersion: 4
buildTarget: DefaultTexturePlatform
maxTextureSize: 1024
resizeAlgorithm: 0
textureFormat: -1
textureCompression: 1
compressionQuality: 50
crunchedCompression: 1
allowsAlphaSplitting: 0
overridden: 0
ignorePlatformSupport: 0
androidETC2FallbackOverride: 0
forceMaximumCompressionQuality_BC6H_BC7: 0
- serializedVersion: 4
buildTarget: Standalone
maxTextureSize: 2048
resizeAlgorithm: 0
textureFormat: -1
textureCompression: 1
compressionQuality: 50
crunchedCompression: 0
allowsAlphaSplitting: 0
overridden: 0
ignorePlatformSupport: 0
androidETC2FallbackOverride: 0
forceMaximumCompressionQuality_BC6H_BC7: 0
- serializedVersion: 4
buildTarget: Android
maxTextureSize: 2048
resizeAlgorithm: 0
textureFormat: -1
textureCompression: 1
compressionQuality: 50
crunchedCompression: 0
allowsAlphaSplitting: 0
overridden: 0
ignorePlatformSupport: 0
androidETC2FallbackOverride: 0
forceMaximumCompressionQuality_BC6H_BC7: 0
spriteSheet:
serializedVersion: 2
sprites:
- serializedVersion: 2
name: how_to_play_goal0020_0
rect:
serializedVersion: 2
x: 0
y: 0
width: 1080
height: 1920
alignment: 0
pivot: {x: 0, y: 0}
border: {x: 0, y: 0, z: 0, w: 0}
customData:
outline: []
physicsShape: []
tessellationDetail: -1
bones: []
spriteID: 7c2cea53809948030800000000000000
internalID: 3496087471285781191
vertices: []
indices:
edges: []
weights: []
outline: []
customData:
physicsShape: []
bones: []
spriteID:
internalID: 0
vertices: []
indices:
edges: []
weights: []
secondaryTextures: []
spriteCustomMetadata:
entries: []
nameFileIdTable:
how_to_play_goal0020_0: 3496087471285781191
mipmapLimitGroupName:
pSDRemoveMatte: 0
userData:
assetBundleName:
assetBundleVariant:
Binary file not shown.

After

Width:  |  Height:  |  Size: 48 KiB

Some files were not shown because too many files have changed in this diff Show More