feat(logging): add advanced logging example with file output
- Created AdvancedLoggingExample class demonstrating composite and file loggers - Implemented multi-file logging setup with separate error and full logs - Added game event and performance logging methods - Included key input handling for log operations (flush, clear) - Setup proper resource disposal on application quit
This commit is contained in:
parent
8647572a37
commit
98d5285b46
7
.idea/.idea.Mario-like platformer/.idea/dictionaries/project.xml
generated
Normal file
7
.idea/.idea.Mario-like platformer/.idea/dictionaries/project.xml
generated
Normal file
@ -0,0 +1,7 @@
|
||||
<component name="ProjectDictionaryState">
|
||||
<dictionary name="project">
|
||||
<words>
|
||||
<w>event'ов</w>
|
||||
</words>
|
||||
</dictionary>
|
||||
</component>
|
||||
6
.idea/.idea.Mario-like platformer/.idea/inspectionProfiles/Project_Default.xml
generated
Normal file
6
.idea/.idea.Mario-like platformer/.idea/inspectionProfiles/Project_Default.xml
generated
Normal file
@ -0,0 +1,6 @@
|
||||
<component name="InspectionProjectProfileManager">
|
||||
<profile version="1.0">
|
||||
<option name="myName" value="Project Default" />
|
||||
<inspection_tool class="TypeScriptLibrary" enabled="true" level="ERROR" enabled_by_default="true" />
|
||||
</profile>
|
||||
</component>
|
||||
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
8
Assets/Fonts.meta
Normal file
8
Assets/Fonts.meta
Normal file
@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: c18aab31685c83e4aade0ec2cc4be64e
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
8
Assets/Fonts/NEW.meta
Normal file
8
Assets/Fonts/NEW.meta
Normal file
@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 8239d7c546e392049b05507ecf82e3e6
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
11357
Assets/Fonts/NEW/NexaText-Regular SDF.asset
Normal file
11357
Assets/Fonts/NEW/NexaText-Regular SDF.asset
Normal file
File diff suppressed because one or more lines are too long
8
Assets/Fonts/NEW/NexaText-Regular SDF.asset.meta
Normal file
8
Assets/Fonts/NEW/NexaText-Regular SDF.asset.meta
Normal file
@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 3f10bbcf486189d4f95b8de6dc2e2177
|
||||
NativeFormatImporter:
|
||||
externalObjects: {}
|
||||
mainObjectFileID: 11400000
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@ -729,6 +729,17 @@
|
||||
"action": "Secret",
|
||||
"isComposite": false,
|
||||
"isPartOfComposite": false
|
||||
},
|
||||
{
|
||||
"name": "",
|
||||
"id": "5e6a0ace-34fd-439a-84e9-cf814f042efa",
|
||||
"path": "<Keyboard>/f3",
|
||||
"interactions": "",
|
||||
"processors": "",
|
||||
"groups": ";Keyboard&Mouse",
|
||||
"action": "Secret",
|
||||
"isComposite": false,
|
||||
"isPartOfComposite": false
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
8
Assets/Prefabs/Level.meta
Normal file
8
Assets/Prefabs/Level.meta
Normal file
@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 377d96ec6ef9ae6429ebb389817b028f
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@ -76,9 +76,9 @@ SpriteRenderer:
|
||||
m_AutoUVMaxAngle: 89
|
||||
m_LightmapParameters: {fileID: 0}
|
||||
m_GlobalIlluminationMeshLod: 0
|
||||
m_SortingLayerID: 0
|
||||
m_SortingLayer: 0
|
||||
m_SortingOrder: 0
|
||||
m_SortingLayerID: 1159882347
|
||||
m_SortingLayer: -1
|
||||
m_SortingOrder: -1
|
||||
m_Sprite: {fileID: 21300000, guid: 6bf6ab5c1534fe44b803733131ceacb9, type: 3}
|
||||
m_Color: {r: 1, g: 1, b: 1, a: 1}
|
||||
m_FlipX: 0
|
||||
@ -186,4 +186,7 @@ MonoBehaviour:
|
||||
spawnForward: {x: 1, y: 0}
|
||||
playerTag: Player
|
||||
activateVfx: {fileID: 0}
|
||||
activateSfx: {fileID: 0}
|
||||
activateSfx:
|
||||
sound: {fileID: 0}
|
||||
volume: 0
|
||||
pitch: 0
|
||||
@ -10,6 +10,7 @@ GameObject:
|
||||
m_Component:
|
||||
- component: {fileID: 6708844088101150}
|
||||
- component: {fileID: -6830167632558745604}
|
||||
- component: {fileID: 7290507550622501242}
|
||||
- component: {fileID: 4577859410310799261}
|
||||
- component: {fileID: -6245296037342915518}
|
||||
- component: {fileID: 6566017136146807207}
|
||||
@ -48,6 +49,19 @@ MonoBehaviour:
|
||||
m_Script: {fileID: 11500000, guid: e679be5faf94f304d8251931f02c036a, type: 3}
|
||||
m_Name:
|
||||
m_EditorClassIdentifier: '::'
|
||||
--- !u!114 &7290507550622501242
|
||||
MonoBehaviour:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 4763496076470024150}
|
||||
m_Enabled: 1
|
||||
m_EditorHideFlags: 0
|
||||
m_Script: {fileID: 11500000, guid: a0811f9af9cb5dc4fbd4d2be780bb43f, type: 3}
|
||||
m_Name:
|
||||
m_EditorClassIdentifier: Assembly-CSharp::RR.Common.Managers.SettingsManager
|
||||
gameSettings: {fileID: 11400000, guid: bdc702de5b61eae45a0dc18413673fd8, type: 2}
|
||||
--- !u!114 &4577859410310799261
|
||||
MonoBehaviour:
|
||||
m_ObjectHideFlags: 0
|
||||
|
||||
@ -155,7 +155,7 @@ RectTransform:
|
||||
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
|
||||
m_AnchorMin: {x: 0, y: 1}
|
||||
m_AnchorMax: {x: 0, y: 1}
|
||||
m_AnchoredPosition: {x: 200, y: -75}
|
||||
m_AnchoredPosition: {x: 225, y: -100}
|
||||
m_SizeDelta: {x: 200, y: 100}
|
||||
m_Pivot: {x: 0.5, y: 0.5}
|
||||
--- !u!114 &22609641
|
||||
@ -1536,7 +1536,7 @@ RectTransform:
|
||||
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
|
||||
m_AnchorMin: {x: 0.5, y: 1}
|
||||
m_AnchorMax: {x: 0.5, y: 1}
|
||||
m_AnchoredPosition: {x: 0, y: -75}
|
||||
m_AnchoredPosition: {x: 0, y: -100}
|
||||
m_SizeDelta: {x: 200, y: 100}
|
||||
m_Pivot: {x: 0.5, y: 0.5}
|
||||
--- !u!114 &606480483
|
||||
@ -1734,7 +1734,7 @@ RectTransform:
|
||||
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
|
||||
m_AnchorMin: {x: 1, y: 1}
|
||||
m_AnchorMax: {x: 1, y: 1}
|
||||
m_AnchoredPosition: {x: -125, y: -74.99994}
|
||||
m_AnchoredPosition: {x: -150, y: -100}
|
||||
m_SizeDelta: {x: 200, y: 100}
|
||||
m_Pivot: {x: 0.5, y: 0.5}
|
||||
--- !u!114 &857663739
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
21
Assets/Scenes/SettingsDemp.cs
Normal file
21
Assets/Scenes/SettingsDemp.cs
Normal file
@ -0,0 +1,21 @@
|
||||
// using UnityEngine;
|
||||
//
|
||||
// public class SettingsDemo : MonoBehaviour
|
||||
// {
|
||||
// [SerializeField] private SettingsScreen screen;
|
||||
// void Start()
|
||||
// => screen.Open();
|
||||
//
|
||||
//
|
||||
// void Update()
|
||||
// {
|
||||
// int direction = 0;
|
||||
// if (Input.GetKeyDown(KeyCode.LeftArrow)) direction -= 1;
|
||||
// if (Input.GetKeyDown(KeyCode.RightArrow)) direction += 1;
|
||||
//
|
||||
// screen.Switch(direction);
|
||||
//
|
||||
// if (Input.GetKeyDown(KeyCode.Space)) screen.Accept();
|
||||
//
|
||||
// }
|
||||
// }
|
||||
11
Assets/Scenes/SettingsDemp.cs.meta
Normal file
11
Assets/Scenes/SettingsDemp.cs.meta
Normal file
@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 0bbc476c5afe6544d9b7fb58df71d41e
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
3642
Assets/Scenes/settingsDemo.unity
Normal file
3642
Assets/Scenes/settingsDemo.unity
Normal file
File diff suppressed because it is too large
Load Diff
7
Assets/Scenes/settingsDemo.unity.meta
Normal file
7
Assets/Scenes/settingsDemo.unity.meta
Normal file
@ -0,0 +1,7 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 8d96790d32e90964ca86a7b61d60c7e8
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@ -101,16 +101,16 @@ public class ComInputToInputSystemAdapter : MonoBehaviour
|
||||
|
||||
if (target == TargetTarget.Button)
|
||||
{
|
||||
st = st.WithButton(btn, true);
|
||||
st = st.WithButton(btn);
|
||||
}
|
||||
else
|
||||
{
|
||||
st = dir switch
|
||||
{
|
||||
DpadDir.Up => st.WithButton(GamepadButton.DpadUp, true),
|
||||
DpadDir.Down => st.WithButton(GamepadButton.DpadDown, true),
|
||||
DpadDir.Left => st.WithButton(GamepadButton.DpadLeft, true),
|
||||
DpadDir.Right => st.WithButton(GamepadButton.DpadRight, true),
|
||||
DpadDir.Up => st.WithButton(GamepadButton.DpadUp),
|
||||
DpadDir.Down => st.WithButton(GamepadButton.DpadDown),
|
||||
DpadDir.Left => st.WithButton(GamepadButton.DpadLeft),
|
||||
DpadDir.Right => st.WithButton(GamepadButton.DpadRight),
|
||||
_ => st
|
||||
};
|
||||
}
|
||||
@ -121,7 +121,7 @@ public class ComInputToInputSystemAdapter : MonoBehaviour
|
||||
if (_deviceCreated && _virtualPad != null) return;
|
||||
|
||||
// ищем уже созданный «COM Bridge», чтобы не дублировать
|
||||
foreach (var dev in InputSystem.devices)
|
||||
foreach (InputDevice dev in InputSystem.devices)
|
||||
{
|
||||
if (dev is not Gamepad { description: { product: "COM Bridge Gamepad" } } gp) continue;
|
||||
_virtualPad = gp;
|
||||
|
||||
@ -34,7 +34,7 @@ public class COMInput : InputSource
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Debug.Log($"Что то в COMinput {e.ToString()}");
|
||||
GameManager.Logger.Log("COMInput", $"Что то в COMInput {e.ToString()}");
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
|
||||
@ -1,6 +1,10 @@
|
||||
using System.Text;
|
||||
using System.Collections;
|
||||
using System.Text;
|
||||
using RR.Game2D.Core.Managers;
|
||||
using Unity.VisualScripting;
|
||||
using UnityEngine;
|
||||
using UnityEngine.Events;
|
||||
using UnityEngine.UI;
|
||||
|
||||
/// <summary>
|
||||
/// Основной класс-обертка для работы с COM-портом и периферийной платой.
|
||||
@ -13,8 +17,8 @@ public class ComWrapper : MonoBehaviour
|
||||
[SerializeField] bool enablePrizeChecking = false; // Если хопер с проверкой наличия приза ставим true
|
||||
|
||||
|
||||
public static UnityEvent<int> OnCoinAdded;
|
||||
public static UnityEvent<int> OnCoinRemoved;
|
||||
public static UnityEvent<int> OnCreditAdded;
|
||||
public static UnityEvent<int> OnCreditRemoved;
|
||||
public static UnityEvent<string> OnInputReceived;
|
||||
|
||||
#region Приватные поля
|
||||
@ -45,9 +49,9 @@ public class ComWrapper : MonoBehaviour
|
||||
public void Initialize()
|
||||
{
|
||||
//Создаем ивенты
|
||||
OnCoinAdded = new UnityEvent<int>();
|
||||
OnCoinRemoved = new UnityEvent<int>();
|
||||
OnInputReceived = new();
|
||||
OnCreditAdded = new UnityEvent<int>();
|
||||
OnCreditRemoved = new UnityEvent<int>();
|
||||
OnInputReceived = new UnityEvent<string>();
|
||||
|
||||
//Начальная настройка
|
||||
if (!saveMoneyBetweenSessions) PlayerPrefs.SetInt("CoinsCount", 0);
|
||||
@ -55,7 +59,7 @@ public class ComWrapper : MonoBehaviour
|
||||
initPort(); //вот это важный метод который собственно порт открывает.
|
||||
|
||||
//Каждые 5 сек запрашиваем инпуты у платы. Надо потому что при заходе в игру с пинов еще не пришла инфа
|
||||
if (enablePrizeChecking) InvokeRepeating(nameof(requestInputs), 0, 5);
|
||||
if (enablePrizeChecking) StartCoroutine(KeepPortAliveProcess());
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@ -70,7 +74,7 @@ public class ComWrapper : MonoBehaviour
|
||||
{
|
||||
CreditsCount++;
|
||||
PlayerPrefs.SetInt("CoinsCount", CreditsCount);
|
||||
OnCoinAdded?.Invoke(CreditsCount);
|
||||
OnCreditAdded?.Invoke(CreditsCount);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@ -88,7 +92,7 @@ public class ComWrapper : MonoBehaviour
|
||||
{
|
||||
int w = ComNativeWrapper.Serial_WriteStringUTF8(h, message,
|
||||
1); //w-количество записаных символов в порт. можно обработать
|
||||
//Debug.Log("Wrote: " + w);
|
||||
//GameManager.Logger.Log("Wrote: " + w);
|
||||
|
||||
}
|
||||
catch
|
||||
@ -117,13 +121,19 @@ public class ComWrapper : MonoBehaviour
|
||||
|
||||
mode switch
|
||||
{
|
||||
LightMode.Idle => "106",
|
||||
LightMode.Orange => "107",
|
||||
LightMode.Blue => "108",
|
||||
LightMode.Win => "109",
|
||||
LightMode.Lose => "110",
|
||||
LightMode.Prize => "111",
|
||||
_ => "106"
|
||||
LightMode.Idle1 => "500",
|
||||
LightMode.Idle2 => "507",
|
||||
LightMode.Orange => "501",
|
||||
LightMode.Blue => "502",
|
||||
LightMode.Win => "503",
|
||||
LightMode.Lose => "504",
|
||||
LightMode.Prize => "505",
|
||||
LightMode.Tama => "513",
|
||||
LightMode.Dog => "514",
|
||||
LightMode.Sam => "515",
|
||||
LightMode.Mistress => "516",
|
||||
|
||||
_ => "500"
|
||||
};
|
||||
|
||||
}
|
||||
@ -155,7 +165,7 @@ public class ComWrapper : MonoBehaviour
|
||||
// if (SettingsManager.instance.GetSettingValue("Бесплатная игра") == "Вкл")
|
||||
// {
|
||||
// //Счетчики пробега
|
||||
// PlayerPrefs.SetInt(PrizeSystem.key_starts, PlayerPrefs.GetInt(PrizeSystem.key_starts) + 1);
|
||||
PlayerPrefs.SetInt(PrizeSystem.key_starts, PlayerPrefs.GetInt(PrizeSystem.key_starts) + 1);
|
||||
// PlayerPrefs.SetInt(PrizeSystem.key_startsNul, PlayerPrefs.GetInt(PrizeSystem.key_startsNul) + 1);
|
||||
//
|
||||
// return true;
|
||||
@ -170,35 +180,73 @@ public class ComWrapper : MonoBehaviour
|
||||
PlayerPrefs.SetInt(PrizeSystem.key_starts, PlayerPrefs.GetInt(PrizeSystem.key_starts) + 1);
|
||||
PlayerPrefs.SetInt(PrizeSystem.key_startsNul, PlayerPrefs.GetInt(PrizeSystem.key_startsNul) + 1);
|
||||
|
||||
OnCoinRemoved?.Invoke(CreditsCount);
|
||||
OnCreditRemoved?.Invoke(CreditsCount);
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
//===========================end: PUBLIC API===========================//
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
private void Update() => pollPort();
|
||||
private void OnDisable() => ClosePort();
|
||||
private void OnApplicationQuit() => ClosePort();
|
||||
|
||||
private IEnumerator KeepPortAliveProcess()
|
||||
{
|
||||
OnInputReceived?.AddListener(InputReceivedCather);
|
||||
GameManager.Logger.Log("Подключаю проверку порта.");
|
||||
|
||||
while (true)
|
||||
{
|
||||
requestInputs();
|
||||
yield return new WaitForSeconds(5f);
|
||||
|
||||
//нет инпута
|
||||
if (GetInputToggle() == 0)
|
||||
{
|
||||
GameManager.Logger.Log("Плата отвалилась. Запускаю переподключение.");
|
||||
initPort();
|
||||
|
||||
}
|
||||
//есть инпут
|
||||
else
|
||||
{
|
||||
ToggleInputReceived(0);
|
||||
}
|
||||
|
||||
yield return new WaitForSeconds(5);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void ToggleInputReceived(int value) => PlayerPrefs.SetInt("inputToggle", value);
|
||||
int GetInputToggle() => PlayerPrefs.GetInt("inputToggle", 0);
|
||||
|
||||
void InputReceivedCather(string input)
|
||||
{
|
||||
if (!string.IsNullOrEmpty(input))
|
||||
{
|
||||
//пришел инпут
|
||||
ToggleInputReceived(1);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
#region Приватные методы
|
||||
//Ну тут по дебаг логам все должно быть понятно
|
||||
//Если интересно, то h - это хэндл. Что то на плюсовом, типа ID соединения или чтото. Если 0 то нету соед. если меньше то ошибка, больше 0 - норм.
|
||||
private void initPort()
|
||||
{
|
||||
Debug.Log("Старт программы");
|
||||
GameManager.Logger.Log("ComWrapper", "Старт программы");
|
||||
ComNativeWrapper.Serial_CloseAll();
|
||||
var ports = ComNativeWrapper.ListPorts();
|
||||
Debug.Log("Ports: " + string.Join(", ", ports));
|
||||
if (ports.Length == 0) { Debug.Log("Нет портов, завершаю"); return; }
|
||||
GameManager.Logger.Log("ComWrapper","Ports: " + string.Join(", ", ports));
|
||||
if (ports.Length == 0) { GameManager.Logger.Log("Нет портов, завершаю"); return; }
|
||||
|
||||
string port = ports[^1];
|
||||
Debug.Log("Открываю первый с конца порт: " + port);
|
||||
GameManager.Logger.Log("ComWrapper","Открываю первый с конца порт: " + port);
|
||||
|
||||
|
||||
//вот эти настройки лучше не ковырять, но если очень хочется можно поменять readTimeoutMs и writeTimeoutMs
|
||||
@ -208,16 +256,21 @@ public class ComWrapper : MonoBehaviour
|
||||
h = ComNativeWrapper.Serial_Open(port, 115200, 8, 0, 1, 5, 10);
|
||||
|
||||
|
||||
Debug.Log($"handle: {h}");
|
||||
GameManager.Logger.Log("ComWrapper",$"handle: {h}");
|
||||
if (h <= 0)
|
||||
{
|
||||
Debug.Log("Open failed: " + ComNativeWrapper.GetLastError());
|
||||
GameManager.Logger.Log("ComWrapper","Open failed: " + ComNativeWrapper.GetLastError());
|
||||
return;
|
||||
}
|
||||
else
|
||||
{
|
||||
GameManager.Logger.Log("ComWrapper",$"Открыл порт: {port}");
|
||||
}
|
||||
}
|
||||
|
||||
private static void ClosePort()
|
||||
{
|
||||
GameManager.Logger.Log("ComWrapper","Закрываю все порты");
|
||||
if (h > 0)
|
||||
{
|
||||
ComNativeWrapper.Serial_Close(h);
|
||||
@ -229,17 +282,17 @@ public class ComWrapper : MonoBehaviour
|
||||
//Тут чтение, не трогаем(опционально)
|
||||
private static string ReadBufferLine()
|
||||
{
|
||||
|
||||
|
||||
int read = ComNativeWrapper.Serial_ReadLineUTF8_bytes(h, buf, buf.Length);
|
||||
if (read > 0)
|
||||
{
|
||||
var s = Encoding.UTF8.GetString(buf, 0, read);
|
||||
//Debug.Log($"ReadLine len={read} data=[{s}]");
|
||||
//GameManager.Logger.Log($"ReadLine len={read} data=[{s}]");
|
||||
return s;
|
||||
}
|
||||
else if (read < 0)
|
||||
{
|
||||
Debug.Log($"ReadLine err={read} :: {ComNativeWrapper.GetLastError()}");
|
||||
GameManager.Logger.Log("ComWrapper",$"ReadLine err={read} :: {ComNativeWrapper.GetLastError()}");
|
||||
}
|
||||
return "";
|
||||
}
|
||||
@ -262,10 +315,15 @@ public class ComWrapper : MonoBehaviour
|
||||
}
|
||||
public enum LightMode
|
||||
{
|
||||
Idle,
|
||||
Idle1,
|
||||
Idle2,
|
||||
Orange,
|
||||
Blue,
|
||||
Win,
|
||||
Lose,
|
||||
Prize,
|
||||
Tama,
|
||||
Dog,
|
||||
Sam,
|
||||
Mistress
|
||||
}
|
||||
@ -1,4 +1,5 @@
|
||||
using UnityEngine;
|
||||
using RR.Game2D.Core.Managers;
|
||||
using UnityEngine;
|
||||
|
||||
/// <summary>
|
||||
/// Статический фасад для унифицированного доступа к системе ввода.
|
||||
@ -42,7 +43,7 @@ public class In : MonoBehaviour
|
||||
|
||||
|
||||
var success = source?.Initialize() ?? false;
|
||||
if (!success) Debug.LogWarning("Не удалось проинициалзировать источник управления.");
|
||||
if (!success) GameManager.Logger.LogWarning("In.cs","Не удалось проинициалзировать источник управления.");
|
||||
}
|
||||
|
||||
// ================================================================================
|
||||
|
||||
8
Assets/Scripts/Managers.meta
Normal file
8
Assets/Scripts/Managers.meta
Normal file
@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 7256e3bbec987684f998648327549db3
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@ -165,6 +165,16 @@ namespace RR.Common.Managers
|
||||
|
||||
#region Public API
|
||||
|
||||
public void SetMusicVolume(float newVolume)
|
||||
{
|
||||
// TODO!!!!!
|
||||
}
|
||||
|
||||
public void SetSfxVolume(float newVolume)
|
||||
{
|
||||
// TODO!!!!!
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Мгновенно запустить музыку (без фейда).
|
||||
/// </summary>
|
||||
@ -261,6 +271,8 @@ namespace RR.Common.Managers
|
||||
PlaySfxAt(chosenEffect.sound, position, chosenEffect.volume, chosenEffect.pitch);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
// ==== Internal helpers ====
|
||||
|
||||
private void StopCrossfadeAndFade()
|
||||
@ -380,6 +392,5 @@ namespace RR.Common.Managers
|
||||
src.Play();
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
@ -4,6 +4,7 @@ using UnityEngine;
|
||||
using UnityEngine.SceneManagement;
|
||||
|
||||
using RR.Common.Managers;
|
||||
using RR.Common.Utility;
|
||||
using RR.Game2D.Behaviour;
|
||||
using RR.Game2D.Entities;
|
||||
|
||||
@ -15,9 +16,19 @@ namespace RR.Game2D.Core.Managers
|
||||
// Singleton instance
|
||||
public static GameManager Instance { get; private set; }
|
||||
|
||||
// AudioManager instance
|
||||
// Logger
|
||||
public static CompositeLogger Logger { get; private set; }
|
||||
|
||||
// Game settings
|
||||
public SettingsManager Settings { get; private set; }
|
||||
|
||||
// Audio control for game
|
||||
public AudioManager Audio {get; private set;}
|
||||
|
||||
// Payment control for game
|
||||
|
||||
public PaymentManager Payment {get; private set;}
|
||||
|
||||
// Globals
|
||||
[Header("Globals")]
|
||||
private GameObject globals;
|
||||
@ -35,6 +46,8 @@ namespace RR.Game2D.Core.Managers
|
||||
public int StagesByWorld { get; private set; } = 3;
|
||||
public int Lives { get; set; } = 3;
|
||||
public int Coins { get; private set; } = 0;
|
||||
|
||||
[HideInInspector] public bool ResetLives { get; set; } = true;
|
||||
private float gameStartTime;
|
||||
|
||||
[Header("Игрок")]
|
||||
@ -54,9 +67,7 @@ namespace RR.Game2D.Core.Managers
|
||||
public event Action<float> GameOverEvent; // Когда игрок проигрывает
|
||||
public event Action<float> GameWonEvent; // Когда игрок выигрывает
|
||||
|
||||
//---------------------------
|
||||
// Singleton
|
||||
//---------------------------
|
||||
[RuntimeInitializeOnLoadMethod(RuntimeInitializeLoadType.BeforeSceneLoad)]
|
||||
private static void Bootstrap()
|
||||
{
|
||||
@ -66,18 +77,11 @@ namespace RR.Game2D.Core.Managers
|
||||
Instance = go.AddComponent<GameManager>();
|
||||
DontDestroyOnLoad(go);
|
||||
}
|
||||
// else
|
||||
// {
|
||||
// go = Instance.gameObject;
|
||||
// }
|
||||
//
|
||||
// go.AddComponent<ComWrapper>();
|
||||
// go.AddComponent<In>();
|
||||
// go.AddComponent<PrizeSystem>();
|
||||
}
|
||||
|
||||
private void Awake()
|
||||
{
|
||||
// ---- Singleton ----
|
||||
if (Instance != null && Instance != this)
|
||||
{
|
||||
Destroy(gameObject);
|
||||
@ -86,13 +90,23 @@ namespace RR.Game2D.Core.Managers
|
||||
|
||||
Instance = this;
|
||||
DontDestroyOnLoad(gameObject);
|
||||
// -------------------
|
||||
|
||||
// Initialize Logger
|
||||
if (Logger == null)
|
||||
{
|
||||
Logger = new CompositeLogger();
|
||||
FileLogger fileLogger = new(Path.Combine(Directory.GetParent(Application.dataPath)?.ToString() ?? Application.dataPath, "game.log"));
|
||||
Logger.Initialize(fileLogger);
|
||||
}
|
||||
|
||||
// Initialize Audio control
|
||||
if (Audio == null)
|
||||
{
|
||||
Audio = gameObject.AddComponent<AudioManager>();
|
||||
Audio.Initialize();
|
||||
}
|
||||
|
||||
|
||||
if (globals == null)
|
||||
{
|
||||
GameObject prefab = Resources.Load<GameObject>(globalsPrefabResourcePath);
|
||||
@ -103,19 +117,29 @@ namespace RR.Game2D.Core.Managers
|
||||
}
|
||||
}
|
||||
|
||||
if (Settings == null)
|
||||
{
|
||||
Settings = globals.GetComponent<SettingsManager>();
|
||||
}
|
||||
|
||||
// Initialize Payment control
|
||||
if (Payment == null)
|
||||
{
|
||||
Payment = gameObject.AddComponent<PaymentManager>();
|
||||
Payment.Initialize();
|
||||
}
|
||||
|
||||
gameStartTime = Time.unscaledTime;
|
||||
Debug.Log($"{gameObject.name}: Start time = {gameStartTime}");
|
||||
Logger.Log(gameObject.name,$"Game start time = {gameStartTime}");
|
||||
|
||||
if (SceneManager.GetActiveScene().name != "MainMenu") _shouldSpawnPlayer = true;
|
||||
}
|
||||
|
||||
private void OnDestroy()
|
||||
{
|
||||
Logger = null;
|
||||
if (Instance == this) Instance = null;
|
||||
}
|
||||
//---------------------------
|
||||
//
|
||||
//---------------------------
|
||||
|
||||
//private void Start()
|
||||
//{
|
||||
@ -141,9 +165,11 @@ namespace RR.Game2D.Core.Managers
|
||||
|
||||
if (loaded == null)
|
||||
{
|
||||
Debug.LogError(
|
||||
$"GameManager: playerPrefab is null. Resources.Load('{playerPrefabResourcePath}') вернул null. " +
|
||||
$"Ожидается файл: Assets/Resources/{playerPrefabResourcePath}.prefab (точное совпадение регистра).");
|
||||
Logger.LogError(
|
||||
gameObject.name,
|
||||
$"playerPrefab is null. Resources.Load('{playerPrefabResourcePath}') вернул null." +
|
||||
$" Ожидается файл: Assets/Resources/{playerPrefabResourcePath}.prefab (точное совпадение регистра)."
|
||||
);
|
||||
}
|
||||
return loaded;
|
||||
}
|
||||
@ -217,7 +243,7 @@ namespace RR.Game2D.Core.Managers
|
||||
else
|
||||
{
|
||||
//NewGame();
|
||||
// Debug.Log("WIN");
|
||||
// Logger.Log("WIN");
|
||||
// LoadScene("MainMenu", false);
|
||||
|
||||
// Можно заменить на другое поведение
|
||||
@ -1,4 +1,5 @@
|
||||
using System;
|
||||
using RR.Game2D.Core.Managers;
|
||||
using UnityEngine;
|
||||
using UnityEngine.InputSystem;
|
||||
|
||||
@ -6,6 +7,7 @@ namespace RR.Common.Managers
|
||||
{
|
||||
public class GlobalsManager : MonoBehaviour
|
||||
{
|
||||
private SettingsManager _settingsManager;
|
||||
private ComWrapper _comWrapper;
|
||||
private In _in;
|
||||
private PrizeSystem _prizeSystem;
|
||||
@ -13,6 +15,8 @@ namespace RR.Common.Managers
|
||||
|
||||
private void Awake()
|
||||
{
|
||||
GameManager.Logger.Log(name ,"Initializing global objects...");
|
||||
_settingsManager = GetComponent<SettingsManager>();
|
||||
_comWrapper = GetComponent<ComWrapper>();
|
||||
_in = GetComponent<In>();
|
||||
_prizeSystem = GetComponent<PrizeSystem>();
|
||||
@ -21,11 +25,23 @@ namespace RR.Common.Managers
|
||||
if (_comWrapper == null) gameObject.AddComponent<ComWrapper>();
|
||||
if (_in == null) gameObject.AddComponent<In>();
|
||||
if (_prizeSystem == null) gameObject.AddComponent<PrizeSystem>();
|
||||
if (_settingsManager == null) gameObject.AddComponent<SettingsManager>();
|
||||
if (_adapter == null) gameObject.AddComponent<ComInputToInputSystemAdapter>();
|
||||
|
||||
_settingsManager.Initialize();
|
||||
GameManager.Logger.Log(name, "SettingsManager successfully initialized.");
|
||||
|
||||
_comWrapper.Initialize();
|
||||
GameManager.Logger.Log(name, "ComWrapper successfully initialized.");
|
||||
|
||||
_in.Initialize();
|
||||
GameManager.Logger.Log(name, "In.cs successfully initialized.");
|
||||
|
||||
_prizeSystem.Initialize();
|
||||
GameManager.Logger.Log(name, "PrizeSystem successfully initialized.");
|
||||
|
||||
_adapter.Initialize();
|
||||
GameManager.Logger.Log(name, "InputAdapter successfully initialized.");
|
||||
}
|
||||
}
|
||||
}
|
||||
38
Assets/Scripts/Managers/PaymentManager.cs
Normal file
38
Assets/Scripts/Managers/PaymentManager.cs
Normal file
@ -0,0 +1,38 @@
|
||||
using UnityEngine;
|
||||
|
||||
namespace RR.Common.Managers
|
||||
{
|
||||
public class PaymentManager : MonoBehaviour
|
||||
{
|
||||
public static PaymentManager Instance { get; private set; }
|
||||
|
||||
public int CreditsCount;
|
||||
|
||||
public void Initialize()
|
||||
{
|
||||
if (Instance != null && Instance != this)
|
||||
{
|
||||
Destroy(gameObject);
|
||||
return;
|
||||
}
|
||||
|
||||
Instance = this;
|
||||
DontDestroyOnLoad(gameObject);
|
||||
|
||||
CreditsCount = 0;
|
||||
|
||||
ComWrapper.OnCreditAdded.AddListener(UpdateCredits);
|
||||
}
|
||||
|
||||
private void UpdateCredits(int newCreditsCount)
|
||||
{
|
||||
CreditsCount = newCreditsCount;
|
||||
}
|
||||
|
||||
// Если не инициализируется в GameManager, инициализировать тут
|
||||
// private void Awake()
|
||||
// {
|
||||
// Initialize();
|
||||
// }
|
||||
}
|
||||
}
|
||||
2
Assets/Scripts/Managers/PaymentManager.cs.meta
Normal file
2
Assets/Scripts/Managers/PaymentManager.cs.meta
Normal file
@ -0,0 +1,2 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 60e317a2a046c5644ae8e9281284c244
|
||||
170
Assets/Scripts/Managers/SettingsManager.cs
Normal file
170
Assets/Scripts/Managers/SettingsManager.cs
Normal file
@ -0,0 +1,170 @@
|
||||
using System;
|
||||
using System.IO;
|
||||
using System.Text;
|
||||
using UnityEngine;
|
||||
|
||||
using RR.Game2D.Core.Managers;
|
||||
using RR.Common.Behaviour.ScriptableObjects;
|
||||
|
||||
namespace RR.Common.Managers
|
||||
{
|
||||
public class SettingsManager : MonoBehaviour
|
||||
{
|
||||
public static SettingsManager Instance { get; private set; }
|
||||
|
||||
[SerializeField] private GameSettings gameSettings;
|
||||
|
||||
private const string SETTINGS_FILE_NAME = "settings.json";
|
||||
private string SettingsFilePath => Path.Combine(Application.persistentDataPath, SETTINGS_FILE_NAME);
|
||||
|
||||
public Action OnSettingsLoaded;
|
||||
public Action OnSettingsSaved;
|
||||
|
||||
public void Initialize()
|
||||
{
|
||||
// ---- Singleton ----
|
||||
if (Instance != null && Instance != this)
|
||||
{
|
||||
Destroy(gameObject);
|
||||
return;
|
||||
}
|
||||
|
||||
Instance = this;
|
||||
DontDestroyOnLoad(gameObject);
|
||||
// -------------------
|
||||
|
||||
// Loading and applying game settings
|
||||
if (gameSettings == null)
|
||||
{
|
||||
GameManager.Logger.Log($"{name}: gameSettings is null. Устанавливаю gameSettings по умолчанию.");
|
||||
gameSettings = ScriptableObject.CreateInstance<GameSettings>();
|
||||
}
|
||||
|
||||
LoadSettings();
|
||||
|
||||
gameSettings.ApplySettings();
|
||||
}
|
||||
|
||||
// Если не инициализируется в GameManager, инициализировать тут
|
||||
// private void Awake()
|
||||
// {
|
||||
// Initialize();
|
||||
// }
|
||||
|
||||
private void OnApplicationQuit()
|
||||
{
|
||||
SaveSettings();
|
||||
}
|
||||
|
||||
public void LoadSettings()
|
||||
{
|
||||
if (gameSettings == null)
|
||||
{
|
||||
Debug.LogError($"{name}: gameSettings is null. Невозможно загрузить настройки.");
|
||||
}
|
||||
|
||||
if (File.Exists(SettingsFilePath))
|
||||
{
|
||||
try
|
||||
{
|
||||
string json = File.ReadAllText(SettingsFilePath);
|
||||
Debug.Log($"{name}: Пытаюсь загрузить настройки из: {SettingsFilePath}");
|
||||
Debug.Log($"{name}: Загруженный JSON: {json}");
|
||||
|
||||
GameSettings tempSettings = ScriptableObject.CreateInstance<GameSettings>();
|
||||
JsonUtility.FromJsonOverwrite(json, tempSettings);
|
||||
|
||||
tempSettings.ValidateSettings();
|
||||
JsonUtility.FromJsonOverwrite(json, gameSettings);
|
||||
Debug.Log($"{name}: Настройки загружены и проверены успешно.");
|
||||
Destroy(tempSettings);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Debug.LogError($"{name}: Ошибка при загрузке настроек: {e.Message}. Применяю настройки по умолчанию.");
|
||||
gameSettings.SetDefaultValues();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
Debug.Log($"{name}: Настройки не найдены по пути: {SettingsFilePath}. Применяю настройки по умолчанию.");
|
||||
gameSettings.SetDefaultValues();
|
||||
}
|
||||
|
||||
gameSettings.ApplySettings();
|
||||
OnSettingsLoaded?.Invoke();
|
||||
}
|
||||
|
||||
public void SaveSettings()
|
||||
{
|
||||
if (gameSettings == null)
|
||||
{
|
||||
Debug.LogError($"{name}: gameSettings is null. Невозможно сохранить настройки.");
|
||||
return;
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
string json = JsonUtility.ToJson(gameSettings, true);
|
||||
File.WriteAllText(SettingsFilePath, json, Encoding.UTF8);
|
||||
Debug.Log($"{name}: Настройки сохранены по пути: {SettingsFilePath}.");
|
||||
Debug.Log($"{name}: Сохраненный JSON: {json}");
|
||||
OnSettingsSaved?.Invoke();
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Debug.LogError($"{name}: Ошибка при сохранении настроек: {e.Message}.");
|
||||
}
|
||||
}
|
||||
|
||||
public void SetFullscreen(bool newFullscreen)
|
||||
{
|
||||
gameSettings.isFullscreen = newFullscreen;
|
||||
Debug.Log($"{name}: Установлен режим: {(newFullscreen ? "полноэкранный" : "оконный")}.");
|
||||
}
|
||||
|
||||
public void SetMusicVolume(float newVolume)
|
||||
{
|
||||
gameSettings.musicVolume = newVolume;
|
||||
Debug.Log($"{name}: Установлена громкость музыки: {newVolume}.");
|
||||
}
|
||||
|
||||
public void SetSfxVolume(float newVolume)
|
||||
{
|
||||
gameSettings.sfxVolume = newVolume;
|
||||
Debug.Log($"{name}: Установлена громкость звуков: {newVolume}.");
|
||||
}
|
||||
|
||||
public void SetIsFreeGame(bool newIsFreeGame)
|
||||
{
|
||||
gameSettings.isFreeGame = newIsFreeGame;
|
||||
Debug.Log($"{name}: Установлена флаг 'free game': {newIsFreeGame}.");
|
||||
}
|
||||
|
||||
public void SetIsGivingPrizes(bool newIsGivingPrizes)
|
||||
{
|
||||
gameSettings.isGivingPrizes = newIsGivingPrizes;
|
||||
Debug.Log($"{name}: Установлена флаг 'give prizes': {newIsGivingPrizes}.");
|
||||
}
|
||||
|
||||
public void SetStartLivesCount(int newStartLivesCount)
|
||||
{
|
||||
gameSettings.startLivesCount = newStartLivesCount;
|
||||
Debug.Log($"{name}: Установлен количество жизней: {newStartLivesCount}.");
|
||||
}
|
||||
|
||||
public void SetLivesIncreasedByCredits(int newLivesIncreasedByCredits)
|
||||
{
|
||||
gameSettings.livesIncreasedByCredits = newLivesIncreasedByCredits;
|
||||
Debug.Log($"{name}: Установлены жизни при пополнении баланса: {newLivesIncreasedByCredits}.");
|
||||
}
|
||||
|
||||
public void SetSetLivesToDefaultAfterFirstLose(bool newSetLivesToDefaultAfterFirstLose)
|
||||
{
|
||||
gameSettings.setLivesToDefaultAfterFirstLose = newSetLivesToDefaultAfterFirstLose;
|
||||
Debug.Log($"{name}: Установлен флаг 'set lives to default after first lose': {newSetLivesToDefaultAfterFirstLose}.");
|
||||
}
|
||||
|
||||
public GameSettings GetCurrentGameSettings() => gameSettings;
|
||||
}
|
||||
}
|
||||
2
Assets/Scripts/Managers/SettingsManager.cs.meta
Normal file
2
Assets/Scripts/Managers/SettingsManager.cs.meta
Normal file
@ -0,0 +1,2 @@
|
||||
fileFormatVersion: 2
|
||||
guid: a0811f9af9cb5dc4fbd4d2be780bb43f
|
||||
70
Assets/Scripts/ScriptableObjects/GameSettings.cs
Normal file
70
Assets/Scripts/ScriptableObjects/GameSettings.cs
Normal file
@ -0,0 +1,70 @@
|
||||
using RR.Common.UI;
|
||||
using RR.Game2D.Core.Managers;
|
||||
using UnityEngine;
|
||||
|
||||
namespace RR.Common.Behaviour.ScriptableObjects
|
||||
{
|
||||
[CreateAssetMenu(fileName = "GameSettings", menuName = "Game/GameSettings")]
|
||||
public class GameSettings : ScriptableObject
|
||||
{
|
||||
// General settings
|
||||
public bool isFullscreen;
|
||||
// ATTENTION: Music between 0f and 1f
|
||||
public float musicVolume;
|
||||
public float sfxVolume;
|
||||
|
||||
// Payment settings
|
||||
public bool isFreeGame;
|
||||
public bool isGivingPrizes;
|
||||
|
||||
// Player settings
|
||||
public int startLivesCount;
|
||||
public int livesIncreasedByCredits;
|
||||
public bool setLivesToDefaultAfterFirstLose;
|
||||
|
||||
public void SetDefaultValues()
|
||||
{
|
||||
isFullscreen = true;
|
||||
musicVolume = 1f;
|
||||
sfxVolume = 1f;
|
||||
|
||||
isFreeGame = false;
|
||||
isGivingPrizes = true;
|
||||
|
||||
setLivesToDefaultAfterFirstLose = true;
|
||||
startLivesCount = 3;
|
||||
livesIncreasedByCredits = 1;
|
||||
}
|
||||
|
||||
public void ValidateSettings()
|
||||
{
|
||||
if (musicVolume < 0f || musicVolume > 1f)
|
||||
musicVolume = Mathf.Clamp01(musicVolume);
|
||||
|
||||
if (sfxVolume < 0f || sfxVolume > 1f)
|
||||
sfxVolume = Mathf.Clamp01(sfxVolume);
|
||||
|
||||
if (startLivesCount < 1)
|
||||
startLivesCount = 3;
|
||||
|
||||
if (livesIncreasedByCredits < 0)
|
||||
livesIncreasedByCredits = 0;
|
||||
}
|
||||
|
||||
public void ApplySettings()
|
||||
{
|
||||
if (isFullscreen)
|
||||
FullscreenToggle.SetFullscreen(isFullscreen);
|
||||
|
||||
if (GameManager.Instance != null)
|
||||
{
|
||||
if (!setLivesToDefaultAfterFirstLose)
|
||||
GameManager.Instance.ResetLives = true;
|
||||
|
||||
GameManager.Instance.Audio.SetMusicVolume(musicVolume);
|
||||
GameManager.Instance.Audio.SetSfxVolume(sfxVolume);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
2
Assets/Scripts/ScriptableObjects/GameSettings.cs.meta
Normal file
2
Assets/Scripts/ScriptableObjects/GameSettings.cs.meta
Normal file
@ -0,0 +1,2 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 72dfd8e4297157e468c4edf1a3b4808b
|
||||
22
Assets/Scripts/ScriptableObjects/MainSettings.asset
Normal file
22
Assets/Scripts/ScriptableObjects/MainSettings.asset
Normal file
@ -0,0 +1,22 @@
|
||||
%YAML 1.1
|
||||
%TAG !u! tag:unity3d.com,2011:
|
||||
--- !u!114 &11400000
|
||||
MonoBehaviour:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 0}
|
||||
m_Enabled: 1
|
||||
m_EditorHideFlags: 0
|
||||
m_Script: {fileID: 11500000, guid: 72dfd8e4297157e468c4edf1a3b4808b, type: 3}
|
||||
m_Name: MainSettings
|
||||
m_EditorClassIdentifier: Assembly-CSharp::RR.Common.Behaviour.ScriptableObjects.GameSettings
|
||||
isFullscreen: 1
|
||||
musicVolume: 1
|
||||
sfxVolume: 1
|
||||
isFreeGame: 0
|
||||
isGivingPrizes: 1
|
||||
startLivesCount: 3
|
||||
livesIncreasedByCredits: 1
|
||||
setLivesToDefaultAfterFirstLose: 1
|
||||
8
Assets/Scripts/ScriptableObjects/MainSettings.asset.meta
Normal file
8
Assets/Scripts/ScriptableObjects/MainSettings.asset.meta
Normal file
@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: bdc702de5b61eae45a0dc18413673fd8
|
||||
NativeFormatImporter:
|
||||
externalObjects: {}
|
||||
mainObjectFileID: 11400000
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
8
Assets/Scripts/Settings.meta
Normal file
8
Assets/Scripts/Settings.meta
Normal file
@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: e703b772daf782145a8a21c757d13738
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
136
Assets/Scripts/Settings/OptionPrefab.prefab
Normal file
136
Assets/Scripts/Settings/OptionPrefab.prefab
Normal file
@ -0,0 +1,136 @@
|
||||
%YAML 1.1
|
||||
%TAG !u! tag:unity3d.com,2011:
|
||||
--- !u!1 &7148623651430003250
|
||||
GameObject:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
serializedVersion: 6
|
||||
m_Component:
|
||||
- component: {fileID: 4151967367557128272}
|
||||
- component: {fileID: 6135362282659755657}
|
||||
- component: {fileID: 2094297809795678225}
|
||||
m_Layer: 5
|
||||
m_Name: OptionPrefab
|
||||
m_TagString: Untagged
|
||||
m_Icon: {fileID: 0}
|
||||
m_NavMeshLayer: 0
|
||||
m_StaticEditorFlags: 0
|
||||
m_IsActive: 1
|
||||
--- !u!224 &4151967367557128272
|
||||
RectTransform:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 7148623651430003250}
|
||||
m_LocalRotation: {x: -0, y: -0, z: -0, w: 1}
|
||||
m_LocalPosition: {x: 0, y: 0, z: 0}
|
||||
m_LocalScale: {x: 1, y: 1, z: 1}
|
||||
m_ConstrainProportionsScale: 0
|
||||
m_Children: []
|
||||
m_Father: {fileID: 0}
|
||||
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
|
||||
m_AnchorMin: {x: 0, y: 1}
|
||||
m_AnchorMax: {x: 0, y: 1}
|
||||
m_AnchoredPosition: {x: 600.0001, y: -25.000015}
|
||||
m_SizeDelta: {x: 200, y: 50}
|
||||
m_Pivot: {x: 0, y: 1}
|
||||
--- !u!222 &6135362282659755657
|
||||
CanvasRenderer:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 7148623651430003250}
|
||||
m_CullTransparentMesh: 1
|
||||
--- !u!114 &2094297809795678225
|
||||
MonoBehaviour:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 7148623651430003250}
|
||||
m_Enabled: 1
|
||||
m_EditorHideFlags: 0
|
||||
m_Script: {fileID: 11500000, guid: f4688fdb7df04437aeb418b961361dc5, type: 3}
|
||||
m_Name:
|
||||
m_EditorClassIdentifier:
|
||||
m_Material: {fileID: 0}
|
||||
m_Color: {r: 1, g: 1, b: 1, a: 1}
|
||||
m_RaycastTarget: 1
|
||||
m_RaycastPadding: {x: 0, y: 0, z: 0, w: 0}
|
||||
m_Maskable: 1
|
||||
m_OnCullStateChanged:
|
||||
m_PersistentCalls:
|
||||
m_Calls: []
|
||||
m_text: New Text
|
||||
m_isRightToLeft: 0
|
||||
m_fontAsset: {fileID: 11400000, guid: 3f10bbcf486189d4f95b8de6dc2e2177, type: 2}
|
||||
m_sharedMaterial: {fileID: 4262305343556741190, guid: 3f10bbcf486189d4f95b8de6dc2e2177, type: 2}
|
||||
m_fontSharedMaterials: []
|
||||
m_fontMaterial: {fileID: 0}
|
||||
m_fontMaterials: []
|
||||
m_fontColor32:
|
||||
serializedVersion: 2
|
||||
rgba: 4294967295
|
||||
m_fontColor: {r: 1, g: 1, b: 1, a: 1}
|
||||
m_enableVertexGradient: 0
|
||||
m_colorMode: 3
|
||||
m_fontColorGradient:
|
||||
topLeft: {r: 1, g: 1, b: 1, a: 1}
|
||||
topRight: {r: 1, g: 1, b: 1, a: 1}
|
||||
bottomLeft: {r: 1, g: 1, b: 1, a: 1}
|
||||
bottomRight: {r: 1, g: 1, b: 1, a: 1}
|
||||
m_fontColorGradientPreset: {fileID: 0}
|
||||
m_spriteAsset: {fileID: 0}
|
||||
m_tintAllSprites: 0
|
||||
m_StyleSheet: {fileID: 0}
|
||||
m_TextStyleHashCode: -1183493901
|
||||
m_overrideHtmlColors: 0
|
||||
m_faceColor:
|
||||
serializedVersion: 2
|
||||
rgba: 4294967295
|
||||
m_fontSize: 26
|
||||
m_fontSizeBase: 26
|
||||
m_fontWeight: 400
|
||||
m_enableAutoSizing: 0
|
||||
m_fontSizeMin: 18
|
||||
m_fontSizeMax: 72
|
||||
m_fontStyle: 0
|
||||
m_HorizontalAlignment: 1
|
||||
m_VerticalAlignment: 256
|
||||
m_textAlignment: 65535
|
||||
m_characterSpacing: 0
|
||||
m_wordSpacing: 0
|
||||
m_lineSpacing: 0
|
||||
m_lineSpacingMax: 0
|
||||
m_paragraphSpacing: 0
|
||||
m_charWidthMaxAdj: 0
|
||||
m_enableWordWrapping: 1
|
||||
m_wordWrappingRatios: 0.4
|
||||
m_overflowMode: 0
|
||||
m_linkedTextComponent: {fileID: 0}
|
||||
parentLinkedComponent: {fileID: 0}
|
||||
m_enableKerning: 1
|
||||
m_enableExtraPadding: 0
|
||||
checkPaddingRequired: 0
|
||||
m_isRichText: 1
|
||||
m_parseCtrlCharacters: 1
|
||||
m_isOrthographic: 1
|
||||
m_isCullingEnabled: 0
|
||||
m_horizontalMapping: 0
|
||||
m_verticalMapping: 0
|
||||
m_uvLineOffset: 0
|
||||
m_geometrySortingOrder: 0
|
||||
m_IsTextObjectScaleStatic: 0
|
||||
m_VertexBufferAutoSizeReduction: 0
|
||||
m_useMaxVisibleDescender: 1
|
||||
m_pageToDisplay: 1
|
||||
m_margin: {x: 0, y: 0, z: 0, w: 0}
|
||||
m_isUsingLegacyAnimationComponent: 0
|
||||
m_isVolumetricText: 0
|
||||
m_hasFontAssetChanged: 0
|
||||
m_baseMaterial: {fileID: 0}
|
||||
m_maskOffset: {x: 0, y: 0, z: 0, w: 0}
|
||||
7
Assets/Scripts/Settings/OptionPrefab.prefab.meta
Normal file
7
Assets/Scripts/Settings/OptionPrefab.prefab.meta
Normal file
@ -0,0 +1,7 @@
|
||||
fileFormatVersion: 2
|
||||
guid: bc723f94fd3335c438f8cf47ea6efc4b
|
||||
PrefabImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
136
Assets/Scripts/Settings/SettingPrefab.prefab
Normal file
136
Assets/Scripts/Settings/SettingPrefab.prefab
Normal file
@ -0,0 +1,136 @@
|
||||
%YAML 1.1
|
||||
%TAG !u! tag:unity3d.com,2011:
|
||||
--- !u!1 &4694825826381118814
|
||||
GameObject:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
serializedVersion: 6
|
||||
m_Component:
|
||||
- component: {fileID: 1856242640539414942}
|
||||
- component: {fileID: 4462460912188239392}
|
||||
- component: {fileID: 8886594288047508638}
|
||||
m_Layer: 5
|
||||
m_Name: SettingPrefab
|
||||
m_TagString: Untagged
|
||||
m_Icon: {fileID: 0}
|
||||
m_NavMeshLayer: 0
|
||||
m_StaticEditorFlags: 0
|
||||
m_IsActive: 1
|
||||
--- !u!224 &1856242640539414942
|
||||
RectTransform:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 4694825826381118814}
|
||||
m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
|
||||
m_LocalPosition: {x: 0, y: 0, z: 0}
|
||||
m_LocalScale: {x: 1, y: 1, z: 1}
|
||||
m_ConstrainProportionsScale: 0
|
||||
m_Children: []
|
||||
m_Father: {fileID: 0}
|
||||
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
|
||||
m_AnchorMin: {x: 0, y: 1}
|
||||
m_AnchorMax: {x: 0, y: 1}
|
||||
m_AnchoredPosition: {x: 50, y: -50.00003}
|
||||
m_SizeDelta: {x: 550, y: 50}
|
||||
m_Pivot: {x: 0, y: 0.5}
|
||||
--- !u!222 &4462460912188239392
|
||||
CanvasRenderer:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 4694825826381118814}
|
||||
m_CullTransparentMesh: 1
|
||||
--- !u!114 &8886594288047508638
|
||||
MonoBehaviour:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 4694825826381118814}
|
||||
m_Enabled: 1
|
||||
m_EditorHideFlags: 0
|
||||
m_Script: {fileID: 11500000, guid: f4688fdb7df04437aeb418b961361dc5, type: 3}
|
||||
m_Name:
|
||||
m_EditorClassIdentifier:
|
||||
m_Material: {fileID: 0}
|
||||
m_Color: {r: 1, g: 1, b: 1, a: 1}
|
||||
m_RaycastTarget: 1
|
||||
m_RaycastPadding: {x: 0, y: 0, z: 0, w: 0}
|
||||
m_Maskable: 1
|
||||
m_OnCullStateChanged:
|
||||
m_PersistentCalls:
|
||||
m_Calls: []
|
||||
m_text: New Text
|
||||
m_isRightToLeft: 0
|
||||
m_fontAsset: {fileID: 11400000, guid: 3f10bbcf486189d4f95b8de6dc2e2177, type: 2}
|
||||
m_sharedMaterial: {fileID: 4262305343556741190, guid: 3f10bbcf486189d4f95b8de6dc2e2177, type: 2}
|
||||
m_fontSharedMaterials: []
|
||||
m_fontMaterial: {fileID: 0}
|
||||
m_fontMaterials: []
|
||||
m_fontColor32:
|
||||
serializedVersion: 2
|
||||
rgba: 4294967295
|
||||
m_fontColor: {r: 1, g: 1, b: 1, a: 1}
|
||||
m_enableVertexGradient: 0
|
||||
m_colorMode: 3
|
||||
m_fontColorGradient:
|
||||
topLeft: {r: 1, g: 1, b: 1, a: 1}
|
||||
topRight: {r: 1, g: 1, b: 1, a: 1}
|
||||
bottomLeft: {r: 1, g: 1, b: 1, a: 1}
|
||||
bottomRight: {r: 1, g: 1, b: 1, a: 1}
|
||||
m_fontColorGradientPreset: {fileID: 0}
|
||||
m_spriteAsset: {fileID: 0}
|
||||
m_tintAllSprites: 0
|
||||
m_StyleSheet: {fileID: 0}
|
||||
m_TextStyleHashCode: -1183493901
|
||||
m_overrideHtmlColors: 0
|
||||
m_faceColor:
|
||||
serializedVersion: 2
|
||||
rgba: 4294967295
|
||||
m_fontSize: 26
|
||||
m_fontSizeBase: 26
|
||||
m_fontWeight: 400
|
||||
m_enableAutoSizing: 0
|
||||
m_fontSizeMin: 18
|
||||
m_fontSizeMax: 72
|
||||
m_fontStyle: 0
|
||||
m_HorizontalAlignment: 1
|
||||
m_VerticalAlignment: 512
|
||||
m_textAlignment: 65535
|
||||
m_characterSpacing: 0
|
||||
m_wordSpacing: 0
|
||||
m_lineSpacing: 0
|
||||
m_lineSpacingMax: 0
|
||||
m_paragraphSpacing: 0
|
||||
m_charWidthMaxAdj: 0
|
||||
m_enableWordWrapping: 1
|
||||
m_wordWrappingRatios: 0.4
|
||||
m_overflowMode: 0
|
||||
m_linkedTextComponent: {fileID: 0}
|
||||
parentLinkedComponent: {fileID: 0}
|
||||
m_enableKerning: 1
|
||||
m_enableExtraPadding: 0
|
||||
checkPaddingRequired: 0
|
||||
m_isRichText: 1
|
||||
m_parseCtrlCharacters: 1
|
||||
m_isOrthographic: 1
|
||||
m_isCullingEnabled: 0
|
||||
m_horizontalMapping: 0
|
||||
m_verticalMapping: 0
|
||||
m_uvLineOffset: 0
|
||||
m_geometrySortingOrder: 0
|
||||
m_IsTextObjectScaleStatic: 0
|
||||
m_VertexBufferAutoSizeReduction: 0
|
||||
m_useMaxVisibleDescender: 1
|
||||
m_pageToDisplay: 1
|
||||
m_margin: {x: 0, y: 0, z: 0, w: 0}
|
||||
m_isUsingLegacyAnimationComponent: 0
|
||||
m_isVolumetricText: 0
|
||||
m_hasFontAssetChanged: 0
|
||||
m_baseMaterial: {fileID: 0}
|
||||
m_maskOffset: {x: 0, y: 0, z: 0, w: 0}
|
||||
7
Assets/Scripts/Settings/SettingPrefab.prefab.meta
Normal file
7
Assets/Scripts/Settings/SettingPrefab.prefab.meta
Normal file
@ -0,0 +1,7 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 959fadb1ff4c40540baceea041c5ab3f
|
||||
PrefabImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
3
Assets/Scripts/Settings/_sega.meta
Normal file
3
Assets/Scripts/Settings/_sega.meta
Normal file
@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 8822d9ad6616481f9c86e4c709221bd4
|
||||
timeCreated: 1762348485
|
||||
12
Assets/Scripts/Settings/_sega/GameSettings.cs
Normal file
12
Assets/Scripts/Settings/_sega/GameSettings.cs
Normal file
@ -0,0 +1,12 @@
|
||||
using System.Collections.Generic;
|
||||
|
||||
// [System.Serializable]
|
||||
// public class GameSettings
|
||||
// {
|
||||
// public List<SettingOption> settings;
|
||||
// public int hash;
|
||||
// public SettingOption GetSetting(string settingName)
|
||||
// {
|
||||
// return settings.Find(s => s.settingName == settingName);
|
||||
// }
|
||||
// }
|
||||
11
Assets/Scripts/Settings/_sega/GameSettings.cs.meta
Normal file
11
Assets/Scripts/Settings/_sega/GameSettings.cs.meta
Normal file
@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: de80d69f0b559a94c8ec18aeba347d12
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
20
Assets/Scripts/Settings/_sega/SettingOption.cs
Normal file
20
Assets/Scripts/Settings/_sega/SettingOption.cs
Normal file
@ -0,0 +1,20 @@
|
||||
using System.Collections.Generic;
|
||||
|
||||
[System.Serializable]
|
||||
public class SettingOption
|
||||
{
|
||||
public string settingName;
|
||||
public List<string> options;
|
||||
public int chosenIndex;
|
||||
public int defaultIndex;
|
||||
|
||||
|
||||
public SettingOption(string settingName, List<string> options, int defaultIndex)
|
||||
{
|
||||
this.settingName = settingName;
|
||||
this.options = options;
|
||||
this.defaultIndex = defaultIndex;
|
||||
this.chosenIndex = defaultIndex;
|
||||
}
|
||||
public string ChosenOption => options[chosenIndex];
|
||||
}
|
||||
11
Assets/Scripts/Settings/_sega/SettingOption.cs.meta
Normal file
11
Assets/Scripts/Settings/_sega/SettingOption.cs.meta
Normal file
@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 07644b6c546b12047a530b34680101a8
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
158
Assets/Scripts/Settings/_sega/SettingsCombination.cs
Normal file
158
Assets/Scripts/Settings/_sega/SettingsCombination.cs
Normal file
@ -0,0 +1,158 @@
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using RR.Game2D.Core.Managers;
|
||||
using TMPro;
|
||||
using UnityEngine;
|
||||
using UnityEngine.UI;
|
||||
|
||||
public class SettingsCombination : MonoBehaviour
|
||||
{
|
||||
GameManager gm;
|
||||
float resetStartsTimer = 0;
|
||||
float resetGivenPrizesTimer = 0;
|
||||
float setNumber = 0;
|
||||
float telegram = 0;
|
||||
|
||||
float timeToReset = 5;
|
||||
|
||||
string PRIZE_BASE = "Счетчик призов ";
|
||||
string STARTS_BASE = "Внесено монет ";
|
||||
string NULLABLE = "(обнуляемый)";
|
||||
string UNNULLABLE = "(глобальный)";
|
||||
public TextMeshProUGUI starts, startsNul, prize, prizeNul;
|
||||
public Image startsTimerImage, prizeTimerImage, numberImage, telegramImage;
|
||||
|
||||
|
||||
void OnEnable()
|
||||
{
|
||||
gm = GameManager.Instance;
|
||||
RefreshUI();
|
||||
}
|
||||
void Update()
|
||||
{
|
||||
//сброс монет
|
||||
bool condition = In.GetButton(ButtonPinMapping.left1) &&
|
||||
In.GetButton(ButtonPinMapping.right1) &&
|
||||
In.GetButton(ButtonPinMapping.left2) &&
|
||||
In.GetButton(ButtonPinMapping.right2);
|
||||
if (condition)
|
||||
{
|
||||
|
||||
resetStartsTimer += Time.deltaTime;
|
||||
startsTimerImage.fillAmount = resetStartsTimer / timeToReset;
|
||||
|
||||
if (resetStartsTimer >= timeToReset)
|
||||
{
|
||||
ResetStarts();
|
||||
resetStartsTimer = 0;
|
||||
}
|
||||
return;
|
||||
}
|
||||
else
|
||||
{
|
||||
resetStartsTimer -= Time.deltaTime;
|
||||
resetStartsTimer = Mathf.Clamp(resetStartsTimer, 0, 5);
|
||||
startsTimerImage.fillAmount = 0;
|
||||
}
|
||||
|
||||
//телега
|
||||
condition = In.GetButton(ButtonPinMapping.left1) &&
|
||||
In.GetButton(ButtonPinMapping.right1) &&
|
||||
/*In.GetButton(ButtonPinMapping.left2) &&*/
|
||||
In.GetButton(ButtonPinMapping.right2);
|
||||
if (condition)
|
||||
{
|
||||
telegram += Time.deltaTime;
|
||||
telegramImage.fillAmount = telegram / timeToReset;
|
||||
if (telegram >= timeToReset)
|
||||
{
|
||||
//Тут надо зайти в ввод номера
|
||||
telegram = 0;
|
||||
// gm.stateMachine.ChangeState(new EnterTelegramState());
|
||||
//GetNumber();
|
||||
}
|
||||
return;
|
||||
}
|
||||
else
|
||||
{
|
||||
telegram -= Time.deltaTime;
|
||||
telegram = Mathf.Clamp(setNumber, 0, 5);
|
||||
telegramImage.fillAmount = 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
//выданные призы
|
||||
condition = In.GetButton(ButtonPinMapping.left1) &&
|
||||
In.GetButton(ButtonPinMapping.left2);
|
||||
if (condition)
|
||||
{
|
||||
resetGivenPrizesTimer += Time.deltaTime;
|
||||
prizeTimerImage.fillAmount = resetGivenPrizesTimer / timeToReset;
|
||||
if (resetGivenPrizesTimer >= timeToReset)
|
||||
{
|
||||
ResetPrizes();
|
||||
resetGivenPrizesTimer = 0;
|
||||
}
|
||||
return;
|
||||
}
|
||||
else
|
||||
{
|
||||
resetGivenPrizesTimer -= Time.deltaTime;
|
||||
resetGivenPrizesTimer = Mathf.Clamp(resetGivenPrizesTimer, 0, 5);
|
||||
prizeTimerImage.fillAmount = 0;
|
||||
}
|
||||
|
||||
|
||||
//условие захода в ввод номера
|
||||
condition = In.GetButton(ButtonPinMapping.right1) &&
|
||||
In.GetButton(ButtonPinMapping.right2);
|
||||
if (condition)
|
||||
{
|
||||
setNumber += Time.deltaTime;
|
||||
numberImage.fillAmount = setNumber / timeToReset;
|
||||
if (setNumber >= timeToReset)
|
||||
{
|
||||
//Тут надо зайти в ввод номера
|
||||
setNumber = 0;
|
||||
GetNumber();
|
||||
}
|
||||
return;
|
||||
}
|
||||
else
|
||||
{
|
||||
setNumber -= Time.deltaTime;
|
||||
setNumber = Mathf.Clamp(setNumber, 0, 5);
|
||||
numberImage.fillAmount = 0;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
void ResetStarts()
|
||||
{
|
||||
PlayerPrefs.SetInt(PrizeSystem.key_startsNul, 0);
|
||||
RefreshUI();
|
||||
}
|
||||
void ResetPrizes()
|
||||
{
|
||||
PlayerPrefs.SetInt(PrizeSystem.key_prizesgivenNul, 0);
|
||||
RefreshUI();
|
||||
}
|
||||
|
||||
void GetNumber()
|
||||
{
|
||||
// GameManager.instance.stateMachine.ChangeState(new GetNumberState());
|
||||
}
|
||||
|
||||
|
||||
void RefreshUI()
|
||||
{
|
||||
starts.text = STARTS_BASE + UNNULLABLE + ": " + PlayerPrefs.GetInt(PrizeSystem.key_starts);
|
||||
startsNul.text = STARTS_BASE + NULLABLE + ": " + PlayerPrefs.GetInt(PrizeSystem.key_startsNul);
|
||||
|
||||
prize.text = PRIZE_BASE + UNNULLABLE + ": " + PlayerPrefs.GetInt(PrizeSystem.key_prizesgiven);
|
||||
prizeNul.text = PRIZE_BASE + NULLABLE + ": " + PlayerPrefs.GetInt(PrizeSystem.key_prizesgivenNul);
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,2 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 61414424e8ee73b4cbc8b75b1c0216d9
|
||||
137
Assets/Scripts/Settings/_sega/SettingsManager.cs
Normal file
137
Assets/Scripts/Settings/_sega/SettingsManager.cs
Normal file
@ -0,0 +1,137 @@
|
||||
// using System.Text;
|
||||
// using System.Collections.Generic;
|
||||
// using UnityEngine;
|
||||
// using UnityEngine.Events;
|
||||
//
|
||||
// using RR.Common.Behaviour.ScriptableObjects;
|
||||
//
|
||||
// public class SettingsManager : MonoBehaviour
|
||||
// {
|
||||
// public static SettingsManager instance;
|
||||
// public GameSettings gameSettings;
|
||||
// const string SETTINGS_PREFS_KEY = "SETTINGS";
|
||||
// int ActualHash => settingsHash(getDefaultSettings());
|
||||
//
|
||||
// public UnityEvent OnSettingsChanged;
|
||||
//
|
||||
// private void Awake()
|
||||
// {
|
||||
// instance ??= this;
|
||||
// OnSettingsChanged = new UnityEvent();
|
||||
//
|
||||
// LoadOrCreateSettings();
|
||||
// }
|
||||
// private void LoadOrCreateSettings()
|
||||
// {
|
||||
// bool shouldLoadDefault = !PlayerPrefs.HasKey(SETTINGS_PREFS_KEY) || !IsSavedSettingsValid();
|
||||
//
|
||||
// if (shouldLoadDefault)
|
||||
// {
|
||||
// LoadDefaultSettings();
|
||||
// }
|
||||
// else
|
||||
// {
|
||||
// LoadSettings();
|
||||
// }
|
||||
//
|
||||
// bool IsSavedSettingsValid()
|
||||
// {
|
||||
// LoadSettings();
|
||||
// return gameSettings.hash == ActualHash;
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// public void ChangeSetting(string settingName, int newIndex)
|
||||
// {
|
||||
// var setting = gameSettings.GetSetting(settingName);
|
||||
// if (setting != null && newIndex >= 0 && newIndex < setting.options.Count)
|
||||
// {
|
||||
// setting.chosenIndex = newIndex;
|
||||
// SaveSettings();
|
||||
// }
|
||||
// }
|
||||
// public void SaveSettings()
|
||||
// {
|
||||
// string json = JsonUtility.ToJson(gameSettings);
|
||||
//
|
||||
// PlayerPrefs.SetString(SETTINGS_PREFS_KEY, json);
|
||||
// PlayerPrefs.Save();
|
||||
// OnSettingsChanged?.Invoke();
|
||||
// }
|
||||
//
|
||||
// public string GetSettingValue(string settingName)
|
||||
// => gameSettings.GetSetting(settingName).ChosenOption;
|
||||
//
|
||||
//
|
||||
// int settingsHash(List<SettingOption> settings)
|
||||
// {
|
||||
// StringBuilder sb = new StringBuilder();
|
||||
// foreach (SettingOption settingOption in settings)
|
||||
// {
|
||||
// sb.Append(settingOption.settingName);
|
||||
// foreach (string option in settingOption.options)
|
||||
// {
|
||||
// sb.Append(option);
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// int hash = sb.ToString().GetHashCode();
|
||||
// return hash;
|
||||
// }
|
||||
//
|
||||
// void LoadDefaultSettings()
|
||||
// {
|
||||
// //print("Загрузка стандартных настроек");
|
||||
//
|
||||
// gameSettings.settings = getDefaultSettings();
|
||||
// gameSettings.hash = settingsHash(gameSettings.settings);
|
||||
//
|
||||
// SaveSettings();
|
||||
// }
|
||||
//
|
||||
// List<SettingOption> getDefaultSettings()
|
||||
// {
|
||||
// List<SettingOption> settings = new List<SettingOption>();
|
||||
//
|
||||
// settings.Add(new SettingOption(settingName: "Громкость музыки",
|
||||
// options: new List<string>() { "0", "1", "2", "3", "4", "5", "6", "7", "8", "9", "10" },
|
||||
// defaultIndex: 1));
|
||||
//
|
||||
// settings.Add(new SettingOption(settingName: "Громкость эффектов",
|
||||
// options: new List<string>() { "0", "1", "2", "3", "4", "5", "6", "7", "8", "9", "10" },
|
||||
// defaultIndex: 8));
|
||||
//
|
||||
// settings.Add(new SettingOption(settingName: "Выдача призов при игре с ботом",
|
||||
// options: new List<string>() { "Выдавать", "Не выдавать" },
|
||||
// defaultIndex: 0));
|
||||
//
|
||||
// settings.Add(new SettingOption(settingName: "Озвучка персонажей",
|
||||
// options: new List<string>() { "Вкл", "Выкл" },
|
||||
// defaultIndex: 0));
|
||||
//
|
||||
// settings.Add(new SettingOption(settingName: "Сложность ботов",
|
||||
// options: new List<string>() { "Легкая", "Средняя", "Сложная" },
|
||||
// defaultIndex: 1));
|
||||
//
|
||||
// settings.Add(new SettingOption(settingName: "Бесплатная игра",
|
||||
// options: new List<string>() { "Вкл", "Выкл" },
|
||||
// defaultIndex: 1));
|
||||
//
|
||||
// settings.Add(new SettingOption(settingName: "Показывать контакты администрации",
|
||||
// options: new List<string>() { "Вкл", "Выкл" },
|
||||
// defaultIndex: 0));
|
||||
// return settings;
|
||||
// }
|
||||
//
|
||||
//
|
||||
// void LoadSettings()
|
||||
// {
|
||||
// string json = PlayerPrefs.GetString(SETTINGS_PREFS_KEY);
|
||||
// gameSettings = JsonUtility.FromJson<GameSettings>(json);
|
||||
//
|
||||
// SaveSettings();
|
||||
// }
|
||||
//
|
||||
//
|
||||
//
|
||||
// }
|
||||
11
Assets/Scripts/Settings/_sega/SettingsManager.cs.meta
Normal file
11
Assets/Scripts/Settings/_sega/SettingsManager.cs.meta
Normal file
@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 896b3b244e3f8db4c8a6f4591ca9c68f
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: -60
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
241
Assets/Scripts/Settings/_sega/SettingsScreen.cs
Normal file
241
Assets/Scripts/Settings/_sega/SettingsScreen.cs
Normal file
@ -0,0 +1,241 @@
|
||||
// using System.Collections;
|
||||
// using System.Collections.Generic;
|
||||
// using System.Reflection;
|
||||
// using TMPro;
|
||||
// using UnityEngine;
|
||||
//
|
||||
// public class SettingsScreen : MonoBehaviour
|
||||
// {
|
||||
// [Header("Панель с опциями")]
|
||||
// [SerializeField] RectTransform OptionsRect;
|
||||
//
|
||||
// [Header("Панель с вариантами опций")]
|
||||
// [SerializeField] RectTransform ValuesRect;
|
||||
//
|
||||
// [Header("Указатель опций")]
|
||||
// [SerializeField] RectTransform PointerRect;
|
||||
//
|
||||
// [Header("Префаб текста настройки")]
|
||||
// [SerializeField] GameObject SettingPrefab;
|
||||
//
|
||||
// [Header("Префаб текста опции")]
|
||||
// [SerializeField] GameObject OptionPrefab;
|
||||
//
|
||||
//
|
||||
// List<GameObject> settingsLabels;
|
||||
// List<GameObject> optionsLabels;
|
||||
//
|
||||
// substate currentState;
|
||||
//
|
||||
// List<SettingOption> gameSettings => SettingsManager.instance.gameSettings.settings;
|
||||
// int settingsAmount => SettingsManager.instance.gameSettings.settings.Count;
|
||||
// List<string> chosenSettingOptions => SettingsManager.instance.gameSettings.settings[currentSettingIndex].options;
|
||||
// int chosenSettingOptionsAmount => chosenSettingOptions.Count;
|
||||
//
|
||||
//
|
||||
// public int currentSettingIndex = 0;
|
||||
// int currentOptionIndex = 0;
|
||||
//
|
||||
//
|
||||
// float startx = 50;
|
||||
// float starty = -50;
|
||||
//
|
||||
// //float offsetx = 100;
|
||||
// float offsetx = 0;
|
||||
// float offsety = 70;
|
||||
//
|
||||
// Coroutine chooseOption;
|
||||
//
|
||||
// [SerializeField] float optionsPadding = 20;
|
||||
//
|
||||
// public void Open()
|
||||
// {
|
||||
// optionsLabels = new();
|
||||
// settingsLabels = new();
|
||||
// PointerRect.gameObject.SetActive(true);
|
||||
// currentState = substate.SettingChoosing;
|
||||
// currentSettingIndex = 0;
|
||||
// CreateSettingsLabels();
|
||||
// }
|
||||
//
|
||||
// public void Close()
|
||||
// {
|
||||
// ClearOptionsPanel();
|
||||
// ClearSettingsPanel();
|
||||
// if (chooseOption != null) StopCoroutine(chooseOption);
|
||||
// }
|
||||
//
|
||||
// public void Switch(int direction)
|
||||
// {
|
||||
// switch (currentState)
|
||||
// {
|
||||
// case substate.SettingChoosing:
|
||||
// currentSettingIndex = (currentSettingIndex + settingsAmount + direction) % settingsAmount;
|
||||
// PointerRect.anchoredPosition = new Vector2(startx + currentSettingIndex * offsetx, starty - currentSettingIndex * offsety);
|
||||
// break;
|
||||
// case substate.OptionChoosing:
|
||||
// currentOptionIndex = (currentOptionIndex + chosenSettingOptionsAmount + direction) % chosenSettingOptionsAmount;//ТУТ НАДО КОЛИЧЕСТВО ОПЦИЙ НАСТРОЙКИ ПОЛУЧИТЬ
|
||||
// break;
|
||||
// }
|
||||
// //SoundManager.instance.playSwitch();
|
||||
// }
|
||||
//
|
||||
// //менять состояние, сохранять данные
|
||||
// public void Accept()
|
||||
// {
|
||||
// if (currentState == substate.SettingChoosing)
|
||||
// {
|
||||
// createOptionsLabels(gameSettings[currentSettingIndex]);
|
||||
// currentState = substate.OptionChoosing;
|
||||
// PointerRect.gameObject.SetActive(false);
|
||||
//
|
||||
// StartCoroutine(DisplayChosenOption());
|
||||
// }
|
||||
//
|
||||
// else if (currentState == substate.OptionChoosing)
|
||||
// {
|
||||
// SettingsManager.instance.ChangeSetting(settingName: gameSettings[currentSettingIndex].settingName,
|
||||
// newIndex: currentOptionIndex);
|
||||
//
|
||||
// PointerRect.gameObject.SetActive(true);
|
||||
// ClearOptionsPanel();
|
||||
// //Обновляем для учета изменений
|
||||
// ClearSettingsPanel();
|
||||
// CreateSettingsLabels();
|
||||
//
|
||||
// if (chooseOption != null) StopCoroutine(chooseOption);
|
||||
//
|
||||
// currentState = substate.SettingChoosing;
|
||||
// }
|
||||
//
|
||||
// //SoundManager.instance.playChoose();
|
||||
//
|
||||
// }
|
||||
//
|
||||
//
|
||||
//
|
||||
// //Шерстим все существующие настройки
|
||||
// //Создаем для каждой настройки текстовое поле
|
||||
// private void CreateSettingsLabels()
|
||||
// {
|
||||
// settingsLabels = new List<GameObject>();
|
||||
// //currentSettingIndex = 0;
|
||||
// for (int i = 0; i < SettingsManager.instance.gameSettings.settings.Count; i++)
|
||||
// {
|
||||
// createLabelFromSettingOption(SettingsManager.instance.gameSettings.settings[i], i);
|
||||
// //currentSettingIndex++;
|
||||
// }
|
||||
// //currentSettingIndex = 0;
|
||||
// PointerRect.anchoredPosition = new Vector2(startx + currentSettingIndex * offsetx, starty - currentSettingIndex * offsety);
|
||||
//
|
||||
// //Процедура которая собственно создает лейблы
|
||||
// void createLabelFromSettingOption(SettingOption option, int index)
|
||||
// {
|
||||
// GameObject label = Instantiate(SettingPrefab, OptionsRect);
|
||||
// label.name = option.settingName + " Setting";
|
||||
// settingsLabels.Add(label);
|
||||
// RectTransform rt = label.GetComponent<RectTransform>();
|
||||
// rt.anchoredPosition = new Vector2(startx + offsetx * index, starty - offsety * index);
|
||||
//
|
||||
// //Звгоняем название настройки
|
||||
// TextMeshProUGUI text = rt.gameObject.GetComponent<TextMeshProUGUI>();
|
||||
// text.text = option.settingName;
|
||||
//
|
||||
// //Текущая включенная опция
|
||||
// GameObject label2 = Instantiate(OptionPrefab, rt);
|
||||
// label2.name = option.settingName + " Value";
|
||||
// RectTransform option_rt = label2.GetComponent<RectTransform>();
|
||||
//
|
||||
// option_rt.anchoredPosition = new Vector2(rt.sizeDelta.x, 0);
|
||||
//
|
||||
// text = option_rt.gameObject.GetComponent<TextMeshProUGUI>();
|
||||
// text.text = option.ChosenOption;
|
||||
// }
|
||||
//
|
||||
//
|
||||
// }
|
||||
//
|
||||
// // Опции настроек
|
||||
// void createOptionsLabels(SettingOption option)
|
||||
// {
|
||||
//
|
||||
// currentOptionIndex = 0;
|
||||
//
|
||||
// float labelWidth = (ValuesRect.sizeDelta.x - optionsPadding * 2) / option.options.Count;
|
||||
// float labelHeight = ValuesRect.sizeDelta.y - optionsPadding * 2;
|
||||
// print(ValuesRect.sizeDelta);
|
||||
//
|
||||
// foreach (string optionName in option.options)
|
||||
// {
|
||||
// GameObject label = Instantiate(OptionPrefab, ValuesRect);
|
||||
// optionsLabels.Add(label);
|
||||
//
|
||||
// RectTransform rt = label.GetComponent<RectTransform>();
|
||||
// rt.pivot = new Vector2(0, 1f);
|
||||
// rt.sizeDelta = new Vector2(labelWidth, labelHeight);
|
||||
// rt.anchoredPosition = new Vector2(optionsPadding + labelWidth * currentOptionIndex, optionsPadding);
|
||||
//
|
||||
//
|
||||
// TextMeshProUGUI text = label.GetComponent<TextMeshProUGUI>();
|
||||
// text.text = optionName;
|
||||
// text.alignment = TextAlignmentOptions.Center;
|
||||
// text.color = Color.gray;
|
||||
// currentOptionIndex++;
|
||||
// }
|
||||
// currentOptionIndex = option.chosenIndex;
|
||||
// }
|
||||
// void ClearSettingsPanel()
|
||||
// {
|
||||
// foreach (GameObject label in settingsLabels)
|
||||
// {
|
||||
// Object.Destroy(label);
|
||||
// }
|
||||
// settingsLabels.Clear();
|
||||
// }
|
||||
// void ClearOptionsPanel()
|
||||
// {
|
||||
// foreach (GameObject label in optionsLabels)
|
||||
// {
|
||||
// Object.Destroy(label);
|
||||
// }
|
||||
// optionsLabels?.Clear();
|
||||
// }
|
||||
//
|
||||
// IEnumerator DisplayChosenOption()
|
||||
// {
|
||||
// Color normalColor = Color.gray;
|
||||
// Color highlightedColor = Color.white;
|
||||
//
|
||||
// int normalSize = 26;
|
||||
// int chosenSize = 40;
|
||||
//
|
||||
// List<TextMeshProUGUI> options = new List<TextMeshProUGUI>();
|
||||
// foreach (GameObject label in optionsLabels)
|
||||
// {
|
||||
// options.Add(label.GetComponent<TextMeshProUGUI>());
|
||||
// }
|
||||
//
|
||||
// while (true)
|
||||
// {
|
||||
// for (int i = 0; i < options.Count; i++)
|
||||
// {
|
||||
// if (i == currentOptionIndex)
|
||||
// {
|
||||
// options[i].color = Vector4.MoveTowards(options[i].color, highlightedColor, Time.deltaTime * 5);
|
||||
// options[i].fontSize = Mathf.MoveTowards(options[i].fontSize, chosenSize, Time.deltaTime * 140);
|
||||
// }
|
||||
// else
|
||||
// {
|
||||
// options[i].color = Vector4.MoveTowards(options[i].color, normalColor, Time.deltaTime * 5);
|
||||
// options[i].fontSize = Mathf.MoveTowards(options[i].fontSize, normalSize, Time.deltaTime * 140);
|
||||
// }
|
||||
// }
|
||||
// yield return null;
|
||||
// }
|
||||
//
|
||||
//
|
||||
//
|
||||
// }
|
||||
//
|
||||
// enum substate { SettingChoosing, OptionChoosing }
|
||||
// }
|
||||
11
Assets/Scripts/Settings/_sega/SettingsScreen.cs.meta
Normal file
11
Assets/Scripts/Settings/_sega/SettingsScreen.cs.meta
Normal file
@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: c0343bffc1f51dc4ea7c7d3dc9fc25bf
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@ -77,7 +77,7 @@ namespace RR.Common.UI
|
||||
if (ctx.performed) Toggle();
|
||||
}
|
||||
|
||||
private static void Toggle()
|
||||
public static void Toggle()
|
||||
{
|
||||
if (Application.platform == RuntimePlatform.WebGLPlayer) return;
|
||||
|
||||
@ -97,5 +97,21 @@ namespace RR.Common.UI
|
||||
Screen.SetResolution(w, h, false);
|
||||
}
|
||||
}
|
||||
public static void SetFullscreen(bool fullscreen)
|
||||
{
|
||||
if (Application.platform == RuntimePlatform.WebGLPlayer) return;
|
||||
|
||||
if (fullscreen)
|
||||
{
|
||||
Screen.SetResolution(Display.main.systemWidth, Display.main.systemHeight, true);
|
||||
Screen.fullScreen = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
int w = Mathf.RoundToInt(Display.main.systemWidth * 0.5f);
|
||||
int h = Mathf.RoundToInt(Display.main.systemHeight * 0.5f);
|
||||
Screen.fullScreen = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -6,6 +6,7 @@ using UnityEngine.UI;
|
||||
using RR.Game2D.Core.Managers;
|
||||
using TMPro;
|
||||
using UnityEngine.EventSystems;
|
||||
using Random = System.Random;
|
||||
|
||||
namespace RR.Common.UI
|
||||
{
|
||||
@ -25,20 +26,18 @@ namespace RR.Common.UI
|
||||
|
||||
private void OnEnable()
|
||||
{
|
||||
if (GameManager.Instance != null)
|
||||
{
|
||||
GameManager.Instance.GameWonEvent += OnGameWon;
|
||||
GameManager.Instance.GameOverEvent += OnGameOver;
|
||||
}
|
||||
if (GameManager.Instance == null) return;
|
||||
|
||||
GameManager.Instance.GameWonEvent += OnGameWon;
|
||||
GameManager.Instance.GameOverEvent += OnGameOver;
|
||||
}
|
||||
|
||||
private void OnDisable()
|
||||
{
|
||||
if (GameManager.Instance != null)
|
||||
{
|
||||
GameManager.Instance.GameWonEvent -= OnGameWon;
|
||||
GameManager.Instance.GameOverEvent -= OnGameOver;
|
||||
}
|
||||
if (GameManager.Instance == null) return;
|
||||
|
||||
GameManager.Instance.GameWonEvent -= OnGameWon;
|
||||
GameManager.Instance.GameOverEvent -= OnGameOver;
|
||||
}
|
||||
|
||||
private void Awake()
|
||||
|
||||
@ -17,7 +17,6 @@ public class LoseBannerController : MonoBehaviour
|
||||
[SerializeField] private Button continueButton;
|
||||
[SerializeField] private TextMeshProUGUI continueButtonText;
|
||||
[SerializeField] private float continueButtonCountdown = 10f;
|
||||
[SerializeField] private Button mainMenuButton;
|
||||
|
||||
private Coroutine continueCountdownCoroutine;
|
||||
|
||||
@ -52,9 +51,9 @@ public class LoseBannerController : MonoBehaviour
|
||||
{
|
||||
// EventSystem.current.firstSelectedGameObject = continueButton.gameObject;
|
||||
EventSystem.current.SetSelectedGameObject(continueButton.gameObject);
|
||||
|
||||
|
||||
loseText.text = $"Время игры: {GameEndUIController.FormatTime(gameTime)}";
|
||||
|
||||
|
||||
if (continueButtonCountdown <= 0f)
|
||||
{
|
||||
ContinueClicked?.Invoke();
|
||||
@ -67,9 +66,6 @@ public class LoseBannerController : MonoBehaviour
|
||||
continueButton.gameObject.SetActive(true);
|
||||
continueButton.interactable = true;
|
||||
}
|
||||
//
|
||||
// if (mainMenuButton)
|
||||
// mainMenuButton.gameObject.SetActive(false);
|
||||
|
||||
// Остановим предыдущую корутину, если есть
|
||||
if (continueCountdownCoroutine != null)
|
||||
@ -80,7 +76,7 @@ public class LoseBannerController : MonoBehaviour
|
||||
|
||||
continueCountdownCoroutine = StartCoroutine(ContinueCountdownCoroutine(continueButtonCountdown));
|
||||
}
|
||||
|
||||
|
||||
private IEnumerator ContinueCountdownCoroutine(float duration)
|
||||
{
|
||||
|
||||
|
||||
18
Assets/Scripts/UI/SettingsUI.cs
Normal file
18
Assets/Scripts/UI/SettingsUI.cs
Normal file
@ -0,0 +1,18 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
using UnityEngine.UI;
|
||||
using UnityEngine.InputSystem;
|
||||
using UnityEngine.EventSystems;
|
||||
using RR.Common.Managers;
|
||||
using RR.Game2D.Core.Managers;
|
||||
using RR.Common.Behaviour.ScriptableObjects;
|
||||
|
||||
namespace RR.Common.UI
|
||||
{
|
||||
public class SettingsUI : MonoBehaviour
|
||||
{
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
2
Assets/Scripts/UI/SettingsUI.cs.meta
Normal file
2
Assets/Scripts/UI/SettingsUI.cs.meta
Normal file
@ -0,0 +1,2 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 85d4ced96061fd14592d8a7f7fb824de
|
||||
3
Assets/Scripts/UI/SettingsUI_Temp.cs.meta
Normal file
3
Assets/Scripts/UI/SettingsUI_Temp.cs.meta
Normal file
@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: e2d8fe2933724164a5d76abd4892856c
|
||||
timeCreated: 1762512881
|
||||
175
Assets/Scripts/Utilities/AdvancedLoggingExample.cs
Normal file
175
Assets/Scripts/Utilities/AdvancedLoggingExample.cs
Normal file
@ -0,0 +1,175 @@
|
||||
using UnityEngine;
|
||||
using System;
|
||||
using RR.Common.Utility;
|
||||
|
||||
/// <summary>
|
||||
/// Продвинутый пример использования системы логирования.
|
||||
/// Демонстрирует различные сценарии использования FileLogger и CompositeLogger.
|
||||
/// </summary>
|
||||
public class AdvancedLoggingExample : MonoBehaviour
|
||||
{
|
||||
private CompositeLogger compositeLogger;
|
||||
private FileLogger mainFileLogger;
|
||||
private FileLogger errorFileLogger;
|
||||
|
||||
void Start()
|
||||
{
|
||||
SetupAdvancedLogging();
|
||||
DemonstrateLogging();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Настройка продвинутой системы логирования с несколькими выходными файлами
|
||||
/// </summary>
|
||||
private void SetupAdvancedLogging()
|
||||
{
|
||||
// Создаём композитный логгер
|
||||
compositeLogger = new CompositeLogger();
|
||||
compositeLogger.Initialize();
|
||||
|
||||
// Главный файл - все логи
|
||||
mainFileLogger = new FileLogger(
|
||||
System.IO.Path.Combine(Application.persistentDataPath, "full_log.txt"),
|
||||
append: true
|
||||
);
|
||||
mainFileLogger.filterLogType = LogType.Log; // Все типы сообщений
|
||||
|
||||
// Отдельный файл только для ошибок и исключений
|
||||
errorFileLogger = new FileLogger(
|
||||
System.IO.Path.Combine(Application.persistentDataPath, "errors_only.txt"),
|
||||
append: true
|
||||
);
|
||||
errorFileLogger.filterLogType = LogType.Warning; // Только Warning, Error, Exception
|
||||
|
||||
// Добавляем оба логгера
|
||||
compositeLogger.AddLoggers(mainFileLogger, errorFileLogger);
|
||||
|
||||
Debug.Log($"Логирование настроено. Файлы в: {Application.persistentDataPath}");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Демонстрация различных типов логирования
|
||||
/// </summary>
|
||||
private void DemonstrateLogging()
|
||||
{
|
||||
// Простые сообщения
|
||||
compositeLogger.Log("=== Демонстрация системы логирования ===");
|
||||
|
||||
// Сообщения с тегами
|
||||
compositeLogger.Log("SYSTEM", "Игра инициализирована");
|
||||
compositeLogger.LogWarning("AUDIO", "Громкость музыки установлена в 0.5");
|
||||
|
||||
// Форматированные сообщения
|
||||
string playerName = "Player1";
|
||||
int score = 1000;
|
||||
compositeLogger.LogFormat(LogType.Log, "Игрок {0} набрал {1} очков", playerName, score);
|
||||
|
||||
// Логирование с контекстом
|
||||
compositeLogger.Log("Объект создан", this.gameObject);
|
||||
|
||||
// Имитация ошибки
|
||||
compositeLogger.LogError("ERROR", "Это тестовая ошибка - будет в обоих файлах!");
|
||||
|
||||
// Имитация исключения
|
||||
try
|
||||
{
|
||||
throw new InvalidOperationException("Тестовое исключение для демонстрации");
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
compositeLogger.LogException(ex, this.gameObject);
|
||||
}
|
||||
|
||||
// Информация о путях
|
||||
Debug.Log($"Полный лог: {Application.persistentDataPath}/full_log.txt");
|
||||
Debug.Log($"Только ошибки: {Application.persistentDataPath}/errors_only.txt");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Пример метода для логирования игровых событий
|
||||
/// </summary>
|
||||
public void LogGameEvent(string eventName, params object[] parameters)
|
||||
{
|
||||
string paramStr = string.Join(", ", parameters);
|
||||
compositeLogger.Log("GAME_EVENT", $"{eventName}: {paramStr}");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Пример метода для логирования производительности
|
||||
/// </summary>
|
||||
public void LogPerformance(string operation, float duration)
|
||||
{
|
||||
if (duration > 0.016f) // Больше 16мс (60 FPS)
|
||||
{
|
||||
compositeLogger.LogWarning("PERFORMANCE", $"{operation} занял {duration * 1000:F2}мс");
|
||||
}
|
||||
else
|
||||
{
|
||||
compositeLogger.Log("PERFORMANCE", $"{operation} выполнен за {duration * 1000:F2}мс");
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Пример обёртки для измерения времени выполнения
|
||||
/// </summary>
|
||||
public void PerformOperationWithLogging(string operationName, Action operation)
|
||||
{
|
||||
float startTime = Time.realtimeSinceStartup;
|
||||
|
||||
try
|
||||
{
|
||||
operation.Invoke();
|
||||
float duration = Time.realtimeSinceStartup - startTime;
|
||||
LogPerformance(operationName, duration);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
compositeLogger.LogException(ex);
|
||||
compositeLogger.LogError("OPERATION", $"Операция '{operationName}' завершилась с ошибкой");
|
||||
}
|
||||
}
|
||||
|
||||
void Update()
|
||||
{
|
||||
// Пример: логируем нажатия клавиш
|
||||
if (Input.GetKeyDown(KeyCode.L))
|
||||
{
|
||||
LogGameEvent("KeyPress", "L", Time.time);
|
||||
}
|
||||
|
||||
if (Input.GetKeyDown(KeyCode.F))
|
||||
{
|
||||
// Принудительная запись на диск
|
||||
mainFileLogger.Flush();
|
||||
errorFileLogger.Flush();
|
||||
compositeLogger.Log("SYSTEM", "Логи принудительно сохранены на диск");
|
||||
}
|
||||
|
||||
if (Input.GetKeyDown(KeyCode.C))
|
||||
{
|
||||
// Очистка логов
|
||||
mainFileLogger.Clear();
|
||||
errorFileLogger.Clear();
|
||||
compositeLogger.Log("SYSTEM", "Файлы логов очищены");
|
||||
}
|
||||
}
|
||||
|
||||
void OnApplicationQuit()
|
||||
{
|
||||
compositeLogger.Log("SYSTEM", "Приложение завершается...");
|
||||
|
||||
// Важно: освобождаем ресурсы
|
||||
mainFileLogger?.Dispose();
|
||||
errorFileLogger?.Dispose();
|
||||
|
||||
Debug.Log("Файловые логгеры закрыты");
|
||||
}
|
||||
|
||||
void OnDestroy()
|
||||
{
|
||||
// На всякий случай
|
||||
mainFileLogger?.Dispose();
|
||||
errorFileLogger?.Dispose();
|
||||
}
|
||||
}
|
||||
|
||||
3
Assets/Scripts/Utilities/AdvancedLoggingExample.cs.meta
Normal file
3
Assets/Scripts/Utilities/AdvancedLoggingExample.cs.meta
Normal file
@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 19e26e3438fd4f56aa52414b1ea03657
|
||||
timeCreated: 1762503889
|
||||
354
Assets/Scripts/Utilities/CompositeLogger.cs
Normal file
354
Assets/Scripts/Utilities/CompositeLogger.cs
Normal file
@ -0,0 +1,354 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using UnityEngine;
|
||||
using Object = UnityEngine.Object;
|
||||
|
||||
public class CompositeLogger : ILogger, IDisposable
|
||||
{
|
||||
public ILogHandler logHandler { get; set; }
|
||||
public bool logEnabled { get; set; }
|
||||
public LogType filterLogType { get; set; }
|
||||
|
||||
private ILogger _oldLogger;
|
||||
private readonly List<ILogger> _additiveLoggers = new();
|
||||
|
||||
public void Initialize(ILogger additiveLogger = null)
|
||||
{
|
||||
_oldLogger = Debug.unityLogger;
|
||||
|
||||
logHandler = _oldLogger.logHandler;
|
||||
logEnabled = true;
|
||||
filterLogType = _oldLogger.filterLogType;
|
||||
|
||||
if (additiveLogger != null) _additiveLoggers.Add(additiveLogger);
|
||||
}
|
||||
|
||||
public void AddLogger(ILogger additiveLogger)
|
||||
{
|
||||
if (additiveLogger == null)
|
||||
throw new ArgumentNullException(nameof(additiveLogger));
|
||||
|
||||
_additiveLoggers.Add(additiveLogger);
|
||||
}
|
||||
|
||||
public void AddLoggers(params ILogger[] additiveLoggers)
|
||||
{
|
||||
if (additiveLoggers == null)
|
||||
throw new ArgumentNullException(nameof(additiveLoggers));
|
||||
|
||||
foreach (var logger in additiveLoggers)
|
||||
{
|
||||
if (logger != null)
|
||||
_additiveLoggers.Add(logger);
|
||||
}
|
||||
}
|
||||
|
||||
public void RemoveLogger(ILogger additiveLogger)
|
||||
{
|
||||
_additiveLoggers.Remove(additiveLogger);
|
||||
}
|
||||
|
||||
public void RemoveLoggers(params ILogger[] additiveLoggers)
|
||||
{
|
||||
_additiveLoggers.RemoveAll(additiveLoggers.Contains);
|
||||
}
|
||||
|
||||
public bool IsLogTypeAllowed(LogType logType)
|
||||
{
|
||||
return _oldLogger.IsLogTypeAllowed(logType) || _additiveLoggers.Any(logger => logger.IsLogTypeAllowed(logType));
|
||||
}
|
||||
|
||||
#region Ilogger Implementation
|
||||
|
||||
public void LogFormat(LogType logType, string format, params object[] args)
|
||||
{
|
||||
_oldLogger.LogFormat(logType, format, args);
|
||||
foreach (ILogger additiveLogger in _additiveLoggers)
|
||||
{
|
||||
try
|
||||
{
|
||||
additiveLogger.LogFormat(logType, format, args);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
_oldLogger.LogException(ex);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void LogFormat(LogType logType, Object context, string format, params object[] args)
|
||||
{
|
||||
_oldLogger.LogFormat(logType, context, format, args);
|
||||
foreach (ILogger additiveLogger in _additiveLoggers)
|
||||
{
|
||||
try
|
||||
{
|
||||
additiveLogger.LogFormat(logType, context, format, args);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
_oldLogger.LogException(ex);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void LogException(Exception exception)
|
||||
{
|
||||
_oldLogger.LogException(exception);
|
||||
foreach (ILogger additiveLogger in _additiveLoggers)
|
||||
{
|
||||
try
|
||||
{
|
||||
additiveLogger.LogException(exception);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
_oldLogger.LogException(ex);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void LogException(Exception exception, Object context)
|
||||
{
|
||||
_oldLogger.LogException(exception, context);
|
||||
foreach (ILogger additiveLogger in _additiveLoggers)
|
||||
{
|
||||
try
|
||||
{
|
||||
additiveLogger.LogException(exception, context);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
_oldLogger.LogException(ex);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void Log(object message)
|
||||
{
|
||||
_oldLogger.Log(message);
|
||||
foreach (ILogger additiveLogger in _additiveLoggers)
|
||||
{
|
||||
try
|
||||
{
|
||||
additiveLogger.Log(message);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
_oldLogger.LogException(ex);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void Log(LogType logType, object message)
|
||||
{
|
||||
_oldLogger.Log(logType, message);
|
||||
foreach (ILogger additiveLogger in _additiveLoggers)
|
||||
{
|
||||
try
|
||||
{
|
||||
additiveLogger.Log(logType, message);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
_oldLogger.LogException(ex);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void Log(LogType logType, object message, GameObject gameObject)
|
||||
{
|
||||
_oldLogger.Log(logType, message, gameObject);
|
||||
foreach (ILogger additiveLogger in _additiveLoggers)
|
||||
{
|
||||
try
|
||||
{
|
||||
additiveLogger.Log(logType, message, gameObject);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
_oldLogger.LogException(ex);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void Log(LogType logType, object message, Object context)
|
||||
{
|
||||
_oldLogger.Log(logType, message, context);
|
||||
foreach (ILogger additiveLogger in _additiveLoggers)
|
||||
{
|
||||
try
|
||||
{
|
||||
additiveLogger.Log(logType, message, context);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
_oldLogger.LogException(ex);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void Log(LogType logType, string tag, object message, Object context)
|
||||
{
|
||||
_oldLogger.Log(logType, tag, message, context);
|
||||
foreach (ILogger additiveLogger in _additiveLoggers)
|
||||
{
|
||||
try
|
||||
{
|
||||
additiveLogger.Log(logType, tag, message, context);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
_oldLogger.LogException(ex);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void Log(LogType logType, string tag, object message)
|
||||
{
|
||||
_oldLogger.Log(tag, message);
|
||||
foreach (ILogger additiveLogger in _additiveLoggers)
|
||||
{
|
||||
try
|
||||
{
|
||||
additiveLogger.Log(tag, message);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
_oldLogger.LogException(ex);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void Log(string tag, object message)
|
||||
{
|
||||
_oldLogger.Log(tag, message);
|
||||
foreach (ILogger additiveLogger in _additiveLoggers)
|
||||
{
|
||||
try
|
||||
{
|
||||
additiveLogger.Log(tag, message);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
_oldLogger.LogException(ex);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void Log(string tag, object message, Object context)
|
||||
{
|
||||
_oldLogger.Log(tag, message, context);
|
||||
foreach (ILogger additiveLogger in _additiveLoggers)
|
||||
{
|
||||
try
|
||||
{
|
||||
additiveLogger.Log(tag, message, context);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
_oldLogger.LogException(ex);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void LogWarning(string tag, object message)
|
||||
{
|
||||
_oldLogger.LogWarning(tag, message);
|
||||
foreach (ILogger additiveLogger in _additiveLoggers)
|
||||
{
|
||||
try
|
||||
{
|
||||
additiveLogger.LogWarning(tag, message);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
_oldLogger.LogException(ex);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void LogWarning(string tag, object message, Object context)
|
||||
{
|
||||
_oldLogger.LogWarning(tag, message, context);
|
||||
foreach (ILogger additiveLogger in _additiveLoggers)
|
||||
{
|
||||
try
|
||||
{
|
||||
additiveLogger.LogWarning(tag, message, context);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
_oldLogger.LogException(ex);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void LogError(string tag, object message)
|
||||
{
|
||||
_oldLogger.LogError(tag, message);
|
||||
foreach (ILogger additiveLogger in _additiveLoggers)
|
||||
{
|
||||
try
|
||||
{
|
||||
additiveLogger.LogError(tag, message);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
_oldLogger.LogException(ex);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void LogError(string tag, object message, Object context)
|
||||
{
|
||||
_oldLogger.LogError(tag, message, context);
|
||||
foreach (ILogger additiveLogger in _additiveLoggers)
|
||||
{
|
||||
try
|
||||
{
|
||||
additiveLogger.LogError(tag, message, context);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
_oldLogger.LogException(ex);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
Dispose(true);
|
||||
GC.SuppressFinalize(this);
|
||||
}
|
||||
|
||||
protected virtual void Dispose(bool disposing)
|
||||
{
|
||||
if (!disposing) return;
|
||||
|
||||
lock (_additiveLoggers)
|
||||
{
|
||||
foreach (ILogger additiveLogger in _additiveLoggers.ToArray())
|
||||
{
|
||||
try
|
||||
{
|
||||
if (additiveLogger is IDisposable disposableLogger)
|
||||
disposableLogger.Dispose();
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
try { _oldLogger?.LogException(ex); } catch { /* ignore */ }
|
||||
}
|
||||
}
|
||||
_additiveLoggers.Clear();
|
||||
}
|
||||
}
|
||||
|
||||
~CompositeLogger()
|
||||
{
|
||||
Dispose();
|
||||
}
|
||||
}
|
||||
2
Assets/Scripts/Utilities/CompositeLogger.cs.meta
Normal file
2
Assets/Scripts/Utilities/CompositeLogger.cs.meta
Normal file
@ -0,0 +1,2 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 7eac28e82d25e9f48925ed67c11f58ac
|
||||
330
Assets/Scripts/Utilities/FileLogger.cs
Normal file
330
Assets/Scripts/Utilities/FileLogger.cs
Normal file
@ -0,0 +1,330 @@
|
||||
using System;
|
||||
using System.IO;
|
||||
using System.Text;
|
||||
using UnityEngine;
|
||||
using Object = UnityEngine.Object;
|
||||
|
||||
|
||||
namespace RR.Common.Utility
|
||||
{
|
||||
/// <summary>
|
||||
/// Логгер для записи сообщений в файл. Совместим с CompositeLogger.
|
||||
/// </summary>
|
||||
public class FileLogger : ILogger, IDisposable
|
||||
{
|
||||
public ILogHandler logHandler { get; set; }
|
||||
public LogType filterLogType { get; set; }
|
||||
|
||||
public bool logEnabled { get; set; } = true;
|
||||
|
||||
private readonly string _filePath;
|
||||
private readonly object _lock = new object();
|
||||
private StreamWriter _writer;
|
||||
private bool _disposed;
|
||||
|
||||
/// <summary>
|
||||
/// Создает файловый логгер с указанным путём к файлу.
|
||||
/// </summary>
|
||||
/// <param name="filePath">Полный путь к файлу лога. Если null, используется Application.persistentDataPath/game.log</param>
|
||||
/// <param name="append">Если true, добавляет к существующему файлу, иначе перезаписывает</param>
|
||||
public FileLogger(string filePath = null, bool append = true)
|
||||
{
|
||||
_filePath = filePath ?? Path.Combine(Application.persistentDataPath, "game.log");
|
||||
filterLogType = LogType.Log;
|
||||
|
||||
try
|
||||
{
|
||||
// Создаем директорию если её нет
|
||||
string directory = Path.GetDirectoryName(_filePath);
|
||||
if (!string.IsNullOrEmpty(directory) && !Directory.Exists(directory))
|
||||
{
|
||||
Directory.CreateDirectory(directory);
|
||||
}
|
||||
|
||||
// Открываем файл для записи
|
||||
_writer = new StreamWriter(_filePath, append, Encoding.UTF8)
|
||||
{
|
||||
AutoFlush = true // Автоматически сбрасывать буфер для надёжности
|
||||
};
|
||||
|
||||
// Записываем заголовок
|
||||
WriteHeader();
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Debug.LogError($"[FileLogger] Не удалось открыть файл лога: {_filePath}\n{ex}");
|
||||
}
|
||||
}
|
||||
|
||||
private void WriteHeader()
|
||||
{
|
||||
if (_writer != null)
|
||||
{
|
||||
_writer.WriteLine("================================================================================");
|
||||
_writer.WriteLine($"Новая сессия логирования начата: {DateTime.Now:yyyy-MM-dd HH:mm:ss}");
|
||||
_writer.WriteLine($"Unity версия: {Application.unityVersion}");
|
||||
_writer.WriteLine($"Платформа: {Application.platform}");
|
||||
_writer.WriteLine($"Путь к логу: {_filePath}");
|
||||
_writer.WriteLine("================================================================================");
|
||||
_writer.WriteLine();
|
||||
}
|
||||
}
|
||||
|
||||
public bool IsLogTypeAllowed(LogType logType)
|
||||
{
|
||||
return logEnabled && logType <= filterLogType;
|
||||
}
|
||||
|
||||
private void WriteToFile(LogType logType, string message)
|
||||
{
|
||||
if (!logEnabled || _disposed || _writer == null)
|
||||
return;
|
||||
|
||||
if (!IsLogTypeAllowed(logType))
|
||||
return;
|
||||
|
||||
lock (_lock)
|
||||
{
|
||||
try
|
||||
{
|
||||
string timestamp = DateTime.Now.ToString("HH:mm:ss.fff");
|
||||
string logTypeStr = GetLogTypeString(logType);
|
||||
_writer.WriteLine($"[{timestamp}] [{logTypeStr}] {message}");
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Debug.LogError($"[FileLogger] Ошибка записи в файл: {ex.Message}");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private string GetLogTypeString(LogType logType)
|
||||
{
|
||||
return logType switch
|
||||
{
|
||||
LogType.Error => "ERROR",
|
||||
LogType.Assert => "ASSERT",
|
||||
LogType.Warning => "WARNING",
|
||||
LogType.Log => "INFO",
|
||||
LogType.Exception => "EXCEPTION",
|
||||
_ => "UNKNOWN"
|
||||
};
|
||||
}
|
||||
|
||||
private string FormatMessage(object message, Object context = null)
|
||||
{
|
||||
string msg = message?.ToString() ?? "null";
|
||||
if (context != null)
|
||||
{
|
||||
msg += $" (Context: {context.name})";
|
||||
}
|
||||
|
||||
return msg;
|
||||
}
|
||||
|
||||
private string FormatMessage(string tag, object message, Object context = null)
|
||||
{
|
||||
string msg = $"[{tag}] {message?.ToString() ?? "null"}";
|
||||
if (context != null)
|
||||
{
|
||||
msg += $" (Context: {context.name})";
|
||||
}
|
||||
|
||||
return msg;
|
||||
}
|
||||
|
||||
#region ILogger Implementation
|
||||
|
||||
public void Log(LogType logType, object message)
|
||||
{
|
||||
WriteToFile(logType, FormatMessage(message));
|
||||
}
|
||||
|
||||
public void Log(LogType logType, object message, Object context)
|
||||
{
|
||||
WriteToFile(logType, FormatMessage(message, context));
|
||||
}
|
||||
|
||||
public void Log(LogType logType, string tag, object message)
|
||||
{
|
||||
WriteToFile(logType, FormatMessage(tag, message));
|
||||
}
|
||||
|
||||
public void Log(LogType logType, string tag, object message, Object context)
|
||||
{
|
||||
WriteToFile(logType, FormatMessage(tag, message, context));
|
||||
}
|
||||
|
||||
public void Log(object message)
|
||||
{
|
||||
WriteToFile(LogType.Log, FormatMessage(message));
|
||||
}
|
||||
|
||||
public void Log(string tag, object message)
|
||||
{
|
||||
WriteToFile(LogType.Log, FormatMessage(tag, message));
|
||||
}
|
||||
|
||||
public void Log(string tag, object message, Object context)
|
||||
{
|
||||
WriteToFile(LogType.Log, FormatMessage(tag, message, context));
|
||||
}
|
||||
|
||||
public void LogWarning(string tag, object message)
|
||||
{
|
||||
WriteToFile(LogType.Warning, FormatMessage(tag, message));
|
||||
}
|
||||
|
||||
public void LogWarning(string tag, object message, Object context)
|
||||
{
|
||||
WriteToFile(LogType.Warning, FormatMessage(tag, message, context));
|
||||
}
|
||||
|
||||
public void LogError(string tag, object message)
|
||||
{
|
||||
WriteToFile(LogType.Error, FormatMessage(tag, message));
|
||||
}
|
||||
|
||||
public void LogError(string tag, object message, Object context)
|
||||
{
|
||||
WriteToFile(LogType.Error, FormatMessage(tag, message, context));
|
||||
}
|
||||
|
||||
public void LogFormat(LogType logType, string format, params object[] args)
|
||||
{
|
||||
try
|
||||
{
|
||||
string message = string.Format(format, args);
|
||||
WriteToFile(logType, message);
|
||||
}
|
||||
catch (FormatException ex)
|
||||
{
|
||||
WriteToFile(LogType.Error, $"Ошибка форматирования: {ex.Message}");
|
||||
}
|
||||
}
|
||||
|
||||
public void LogFormat(LogType logType, Object context, string format, params object[] args)
|
||||
{
|
||||
try
|
||||
{
|
||||
string message = string.Format(format, args);
|
||||
WriteToFile(logType, FormatMessage(message, context));
|
||||
}
|
||||
catch (FormatException ex)
|
||||
{
|
||||
WriteToFile(LogType.Error, $"Ошибка форматирования: {ex.Message}");
|
||||
}
|
||||
}
|
||||
|
||||
public void LogException(Exception exception)
|
||||
{
|
||||
if (exception == null)
|
||||
return;
|
||||
|
||||
WriteToFile(LogType.Exception, $"{exception.GetType().Name}: {exception.Message}");
|
||||
WriteToFile(LogType.Exception, $"StackTrace:\n{exception.StackTrace}");
|
||||
|
||||
if (exception.InnerException != null)
|
||||
{
|
||||
WriteToFile(LogType.Exception,
|
||||
$"Inner Exception: {exception.InnerException.GetType().Name}: {exception.InnerException.Message}");
|
||||
}
|
||||
}
|
||||
|
||||
public void LogException(Exception exception, Object context)
|
||||
{
|
||||
if (exception == null)
|
||||
return;
|
||||
|
||||
string contextInfo = context != null ? $" (Context: {context.name})" : "";
|
||||
WriteToFile(LogType.Exception, $"{exception.GetType().Name}: {exception.Message}{contextInfo}");
|
||||
WriteToFile(LogType.Exception, $"StackTrace:\n{exception.StackTrace}");
|
||||
|
||||
if (exception.InnerException != null)
|
||||
{
|
||||
WriteToFile(LogType.Exception,
|
||||
$"Inner Exception: {exception.InnerException.GetType().Name}: {exception.InnerException.Message}");
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
/// <summary>
|
||||
/// Принудительно сбрасывает буфер на диск
|
||||
/// </summary>
|
||||
public void Flush()
|
||||
{
|
||||
lock (_lock)
|
||||
{
|
||||
try
|
||||
{
|
||||
_writer?.Flush();
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Debug.LogError($"[FileLogger] Ошибка при сбросе буфера: {ex.Message}");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Очищает файл лога
|
||||
/// </summary>
|
||||
public void Clear()
|
||||
{
|
||||
lock (_lock)
|
||||
{
|
||||
try
|
||||
{
|
||||
_writer?.Close();
|
||||
File.WriteAllText(_filePath, string.Empty);
|
||||
_writer = new StreamWriter(_filePath, true, Encoding.UTF8) { AutoFlush = true };
|
||||
WriteHeader();
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Debug.LogError($"[FileLogger] Ошибка при очистке файла: {ex.Message}");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
if (_disposed)
|
||||
return;
|
||||
|
||||
lock (_lock)
|
||||
{
|
||||
try
|
||||
{
|
||||
if (_writer != null)
|
||||
{
|
||||
_writer.WriteLine();
|
||||
_writer.WriteLine(
|
||||
"================================================================================");
|
||||
_writer.WriteLine($"Сессия логирования завершена: {DateTime.Now:yyyy-MM-dd HH:mm:ss}");
|
||||
_writer.WriteLine(
|
||||
"================================================================================");
|
||||
_writer.Flush();
|
||||
_writer.Close();
|
||||
_writer.Dispose();
|
||||
_writer = null;
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Debug.LogError($"[FileLogger] Ошибка при закрытии файла: {ex.Message}");
|
||||
}
|
||||
finally
|
||||
{
|
||||
_disposed = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
~FileLogger()
|
||||
{
|
||||
Dispose();
|
||||
}
|
||||
}
|
||||
}
|
||||
2
Assets/Scripts/Utilities/FileLogger.cs.meta
Normal file
2
Assets/Scripts/Utilities/FileLogger.cs.meta
Normal file
@ -0,0 +1,2 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 28b8d36a996595144b75e4febc509640
|
||||
93
Assets/Scripts/Utilities/LoggerInitializer.cs
Normal file
93
Assets/Scripts/Utilities/LoggerInitializer.cs
Normal file
@ -0,0 +1,93 @@
|
||||
using UnityEngine;
|
||||
|
||||
namespace RR.Common.Utility
|
||||
{
|
||||
/// <summary>
|
||||
/// Пример инициализации системы логирования с CompositeLogger и FileLogger.
|
||||
/// Прикрепите этот скрипт к любому GameObject на сцене.
|
||||
/// </summary>
|
||||
public class LoggerInitializer : MonoBehaviour
|
||||
{
|
||||
[SerializeField] private bool enableFileLogging = true;
|
||||
[SerializeField] private string customLogPath = ""; // Оставьте пустым для использования пути по умолчанию
|
||||
[SerializeField] private bool appendToExistingLog = true;
|
||||
[SerializeField] private bool clearLogOnStart = false;
|
||||
|
||||
private CompositeLogger compositeLogger;
|
||||
private FileLogger fileLogger;
|
||||
|
||||
private void Awake()
|
||||
{
|
||||
InitializeLogging();
|
||||
}
|
||||
|
||||
private void InitializeLogging()
|
||||
{
|
||||
// Создаем композитный логгер
|
||||
compositeLogger = new CompositeLogger();
|
||||
compositeLogger.Initialize();
|
||||
|
||||
if (enableFileLogging)
|
||||
{
|
||||
// Создаем файловый логгер
|
||||
string logPath = string.IsNullOrEmpty(customLogPath) ? null : customLogPath;
|
||||
fileLogger = new FileLogger(logPath, appendToExistingLog);
|
||||
|
||||
if (clearLogOnStart)
|
||||
{
|
||||
fileLogger.Clear();
|
||||
}
|
||||
|
||||
// Добавляем файловый логгер в композитный
|
||||
compositeLogger.AddLogger(fileLogger);
|
||||
|
||||
Debug.Log(
|
||||
$"[LoggerInitializer] Файловое логирование включено. Путь: {(logPath ?? Application.persistentDataPath + "/game.log")}");
|
||||
}
|
||||
|
||||
// Опционально: можно заменить стандартный логгер Unity
|
||||
// Debug.unityLogger = compositeLogger;
|
||||
|
||||
// Тестовые сообщения
|
||||
TestLogging();
|
||||
}
|
||||
|
||||
private void TestLogging()
|
||||
{
|
||||
compositeLogger.Log("Система логирования инициализирована");
|
||||
compositeLogger.LogWarning("Test", "Это тестовое предупреждение");
|
||||
compositeLogger.LogError("Test", "Это тестовая ошибка");
|
||||
|
||||
Debug.Log($"Логи сохраняются в: {Application.persistentDataPath}");
|
||||
}
|
||||
|
||||
private void OnApplicationQuit()
|
||||
{
|
||||
// Закрываем файловый логгер при выходе
|
||||
fileLogger?.Dispose();
|
||||
Debug.Log("[LoggerInitializer] Файловый логгер закрыт");
|
||||
}
|
||||
|
||||
private void OnDestroy()
|
||||
{
|
||||
// На всякий случай закрываем при уничтожении объекта
|
||||
fileLogger?.Dispose();
|
||||
}
|
||||
|
||||
// Публичные методы для использования из других скриптов
|
||||
public static void LogToFile(string message)
|
||||
{
|
||||
Debug.Log(message);
|
||||
}
|
||||
|
||||
public static void LogWarningToFile(string message)
|
||||
{
|
||||
Debug.LogWarning(message);
|
||||
}
|
||||
|
||||
public static void LogErrorToFile(string message)
|
||||
{
|
||||
Debug.LogError(message);
|
||||
}
|
||||
}
|
||||
}
|
||||
3
Assets/Scripts/Utilities/LoggerInitializer.cs.meta
Normal file
3
Assets/Scripts/Utilities/LoggerInitializer.cs.meta
Normal file
@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 8cad0029d1274d6393bd4b7821dd6c6e
|
||||
timeCreated: 1762503813
|
||||
284
Assets/Scripts/Utilities/README_LOGGING.md
Normal file
284
Assets/Scripts/Utilities/README_LOGGING.md
Normal file
@ -0,0 +1,284 @@
|
||||
# Система логирования для Unity
|
||||
|
||||
## Обзор
|
||||
|
||||
Система состоит из трёх компонентов:
|
||||
1. **CompositeLogger** - композитный логгер, пересылающий сообщения на несколько логгеров
|
||||
2. **FileLogger** - логгер для записи в файл
|
||||
3. **LoggerInitializer** - компонент для автоматической инициализации
|
||||
|
||||
## Быстрый старт
|
||||
|
||||
### Вариант 1: Использование через LoggerInitializer (рекомендуется)
|
||||
|
||||
1. Создайте пустой GameObject на сцене
|
||||
2. Прикрепите компонент `LoggerInitializer`
|
||||
3. Настройте параметры в инспекторе:
|
||||
- **Enable File Logging** - включить запись в файл
|
||||
- **Custom Log Path** - путь к файлу (оставьте пустым для автоматического)
|
||||
- **Append To Existing Log** - добавлять к существующему файлу
|
||||
- **Clear Log On Start** - очищать файл при запуске
|
||||
|
||||
4. Запустите игру - все логи будут автоматически писаться в файл!
|
||||
|
||||
### Вариант 2: Ручная настройка в коде
|
||||
|
||||
```csharp
|
||||
using UnityEngine;
|
||||
|
||||
public class MyGameManager : MonoBehaviour
|
||||
{
|
||||
private CompositeLogger compositeLogger;
|
||||
private FileLogger fileLogger;
|
||||
|
||||
void Awake()
|
||||
{
|
||||
// Инициализация композитного логгера
|
||||
compositeLogger = new CompositeLogger();
|
||||
compositeLogger.Initialize();
|
||||
|
||||
// Создание файлового логгера
|
||||
fileLogger = new FileLogger(); // Использует путь по умолчанию
|
||||
// или
|
||||
// fileLogger = new FileLogger("D:/MyGame/logs/game.log", append: true);
|
||||
|
||||
// Добавление файлового логгера в композитный
|
||||
compositeLogger.AddLogger(fileLogger);
|
||||
|
||||
// Теперь все логи через compositeLogger будут идти и в консоль, и в файл
|
||||
compositeLogger.Log("Игра запущена!");
|
||||
compositeLogger.LogWarning("Test", "Тестовое предупреждение");
|
||||
}
|
||||
|
||||
void OnApplicationQuit()
|
||||
{
|
||||
fileLogger?.Dispose();
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## Где находится файл лога?
|
||||
|
||||
По умолчанию файл сохраняется в `Application.persistentDataPath/game.log`:
|
||||
|
||||
- **Windows**: `C:/Users/<Username>/AppData/LocalLow/<CompanyName>/<ProductName>/game.log`
|
||||
- **macOS**: `~/Library/Application Support/<CompanyName>/<ProductName>/game.log`
|
||||
- **Linux**: `~/.config/unity3d/<CompanyName>/<ProductName>/game.log`
|
||||
- **Android**: `/storage/emulated/0/Android/data/<PackageName>/files/game.log`
|
||||
|
||||
Узнать точный путь можно через:
|
||||
```csharp
|
||||
Debug.Log(Application.persistentDataPath);
|
||||
```
|
||||
|
||||
## Примеры использования
|
||||
|
||||
### Базовое логирование
|
||||
|
||||
```csharp
|
||||
// Через композитный логгер
|
||||
compositeLogger.Log("Простое сообщение");
|
||||
compositeLogger.LogWarning("Tag", "Предупреждение");
|
||||
compositeLogger.LogError("Tag", "Ошибка");
|
||||
|
||||
// Через стандартный Debug (если вы заменили Debug.unityLogger)
|
||||
Debug.Log("Это тоже пойдёт в файл");
|
||||
```
|
||||
|
||||
### Логирование с контекстом
|
||||
|
||||
```csharp
|
||||
compositeLogger.Log(LogType.Log, "Игрок спавнится", playerGameObject);
|
||||
compositeLogger.LogWarning("AI", "Путь не найден", enemyGameObject);
|
||||
```
|
||||
|
||||
### Логирование исключений
|
||||
|
||||
```csharp
|
||||
try
|
||||
{
|
||||
// Опасный код
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
compositeLogger.LogException(ex);
|
||||
}
|
||||
```
|
||||
|
||||
### Форматированное логирование
|
||||
|
||||
```csharp
|
||||
compositeLogger.LogFormat(LogType.Log, "Игрок {0} имеет {1} очков здоровья", playerName, health);
|
||||
```
|
||||
|
||||
### Добавление нескольких логгеров
|
||||
|
||||
```csharp
|
||||
var fileLogger1 = new FileLogger("logs/debug.log");
|
||||
var fileLogger2 = new FileLogger("logs/errors.log");
|
||||
fileLogger2.filterLogType = LogType.Error; // Только ошибки
|
||||
|
||||
compositeLogger.AddLoggers(fileLogger1, fileLogger2);
|
||||
```
|
||||
|
||||
## Настройка фильтрации
|
||||
|
||||
### На уровне FileLogger
|
||||
|
||||
```csharp
|
||||
fileLogger.filterLogType = LogType.Warning; // Логировать только Warning, Error, Exception
|
||||
fileLogger.logEnabled = false; // Временно отключить
|
||||
```
|
||||
|
||||
### Очистка файла лога
|
||||
|
||||
```csharp
|
||||
fileLogger.Clear(); // Очистить файл и записать новый заголовок
|
||||
```
|
||||
|
||||
### Принудительная запись на диск
|
||||
|
||||
```csharp
|
||||
fileLogger.Flush(); // Сбросить буфер на диск
|
||||
```
|
||||
|
||||
## Формат записи в файле
|
||||
|
||||
```
|
||||
================================================================================
|
||||
Новая сессия логирования начата: 2025-11-07 14:30:15
|
||||
Unity версия: 2022.3.5f1
|
||||
Платформа: WindowsEditor
|
||||
Путь к логу: C:/Users/User/AppData/LocalLow/DefaultCompany/MyGame/game.log
|
||||
================================================================================
|
||||
|
||||
[14:30:15.123] [INFO] Игра запущена!
|
||||
[14:30:16.456] [WARNING] [AI] Путь не найден
|
||||
[14:30:17.789] [ERROR] [Network] Соединение потеряно
|
||||
[14:30:18.012] [EXCEPTION] NullReferenceException: Object reference not set to an instance of an object
|
||||
StackTrace:
|
||||
at MyScript.MyMethod () [0x00000] in <filename>:0
|
||||
```
|
||||
|
||||
## Важные замечания
|
||||
|
||||
### Потокобезопасность
|
||||
FileLogger потокобезопасен - использует `lock` для синхронизации записи.
|
||||
|
||||
### Производительность
|
||||
- `AutoFlush = true` гарантирует сохранность данных при крашах, но снижает производительность
|
||||
- Если нужна максимальная производительность, установите `AutoFlush = false` и вызывайте `Flush()` вручную
|
||||
|
||||
### Освобождение ресурсов
|
||||
**ВАЖНО:** Всегда вызывайте `Dispose()` при завершении работы:
|
||||
```csharp
|
||||
void OnApplicationQuit()
|
||||
{
|
||||
fileLogger?.Dispose();
|
||||
}
|
||||
```
|
||||
|
||||
### Ротация логов
|
||||
Для больших проектов можно реализовать ротацию:
|
||||
```csharp
|
||||
string timestamp = DateTime.Now.ToString("yyyy-MM-dd_HH-mm-ss");
|
||||
string logPath = $"logs/game_{timestamp}.log";
|
||||
var fileLogger = new FileLogger(logPath, append: false);
|
||||
```
|
||||
|
||||
## Расширенные сценарии
|
||||
|
||||
### Отдельные логи для разных систем
|
||||
|
||||
```csharp
|
||||
// Общий лог
|
||||
var mainLogger = new FileLogger("logs/game.log");
|
||||
|
||||
// Лог только для сетевой подсистемы
|
||||
var networkLogger = new FileLogger("logs/network.log");
|
||||
networkLogger.filterLogType = LogType.Log;
|
||||
|
||||
// Лог только для ошибок
|
||||
var errorLogger = new FileLogger("logs/errors.log");
|
||||
errorLogger.filterLogType = LogType.Error;
|
||||
|
||||
compositeLogger.AddLoggers(mainLogger, networkLogger, errorLogger);
|
||||
```
|
||||
|
||||
### Условное логирование
|
||||
|
||||
```csharp
|
||||
#if UNITY_EDITOR
|
||||
// В редакторе не пишем в файл, только в консоль
|
||||
#else
|
||||
compositeLogger.AddLogger(new FileLogger());
|
||||
#endif
|
||||
```
|
||||
|
||||
### Логирование с метками времени
|
||||
|
||||
```csharp
|
||||
public class TimestampLogger
|
||||
{
|
||||
private CompositeLogger logger;
|
||||
|
||||
public void LogWithTimestamp(string message)
|
||||
{
|
||||
logger.Log($"[{Time.time:F2}s] {message}");
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
### Файл не создаётся
|
||||
- Проверьте права доступа к папке
|
||||
- Проверьте путь через `Debug.Log(Application.persistentDataPath)`
|
||||
- Убедитесь, что вызвали `Initialize()` на CompositeLogger
|
||||
|
||||
### Логи не пишутся в файл
|
||||
- Убедитесь, что `logEnabled = true`
|
||||
- Проверьте `filterLogType` - возможно фильтр слишком строгий
|
||||
- Проверьте, что логгер добавлен через `AddLogger()`
|
||||
|
||||
### Файл заблокирован
|
||||
- Убедитесь, что вызвали `Dispose()` перед закрытием приложения
|
||||
- Закройте все программы, которые могут держать файл открытым
|
||||
|
||||
### Производительность низкая
|
||||
- Установите `AutoFlush = false` в конструкторе FileLogger
|
||||
- Вызывайте `Flush()` периодически (например, раз в секунду)
|
||||
- Используйте более строгий `filterLogType`
|
||||
|
||||
## API Reference
|
||||
|
||||
### FileLogger
|
||||
|
||||
#### Конструктор
|
||||
```csharp
|
||||
FileLogger(string filePath = null, bool append = true)
|
||||
```
|
||||
|
||||
#### Свойства
|
||||
- `bool logEnabled` - включено ли логирование
|
||||
- `LogType filterLogType` - минимальный уровень логирования
|
||||
- `ILogHandler logHandler` - обработчик логов (для совместимости)
|
||||
|
||||
#### Методы
|
||||
- `void Flush()` - принудительно сбросить буфер на диск
|
||||
- `void Clear()` - очистить файл лога
|
||||
- `void Dispose()` - закрыть файл и освободить ресурсы
|
||||
- `bool IsLogTypeAllowed(LogType)` - проверка фильтра
|
||||
|
||||
### CompositeLogger
|
||||
|
||||
#### Методы управления
|
||||
- `void Initialize(ILogger additiveLogger = null)` - инициализация
|
||||
- `void AddLogger(ILogger)` - добавить логгер
|
||||
- `void AddLoggers(params ILogger[])` - добавить несколько логгеров
|
||||
- `void RemoveLogger(ILogger)` - удалить логгер
|
||||
- `void RemoveLoggers(params ILogger[])` - удалить несколько логгеров
|
||||
|
||||
## Лицензия
|
||||
Свободное использование в ваших проектах.
|
||||
|
||||
3
Assets/Scripts/Utilities/README_LOGGING.md.meta
Normal file
3
Assets/Scripts/Utilities/README_LOGGING.md.meta
Normal file
@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: cb2132721bf244f8820de54ff90cb599
|
||||
timeCreated: 1762503862
|
||||
8
Assets/Sprites.meta
Normal file
8
Assets/Sprites.meta
Normal file
@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 4514587d1b9c1ad419ab31158a3910b5
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
8
Assets/Sprites/Graphics.meta
Normal file
8
Assets/Sprites/Graphics.meta
Normal file
@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 2a3d18453b59539458b79a410b71caa8
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
8
Assets/Sprites/Graphics/chips.meta
Normal file
8
Assets/Sprites/Graphics/chips.meta
Normal file
@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 57d3ae40e9eeeab40a18e9f2592e9ef1
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
BIN
Assets/Sprites/Graphics/chips/chip_cat2.png
Normal file
BIN
Assets/Sprites/Graphics/chips/chip_cat2.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 163 KiB |
127
Assets/Sprites/Graphics/chips/chip_cat2.png.meta
Normal file
127
Assets/Sprites/Graphics/chips/chip_cat2.png.meta
Normal file
@ -0,0 +1,127 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 8d6432ff047c62946a41e3235f28ba57
|
||||
TextureImporter:
|
||||
internalIDToNameTable: []
|
||||
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: 1
|
||||
spriteExtrude: 1
|
||||
spriteMeshType: 1
|
||||
alignment: 0
|
||||
spritePivot: {x: 0.5, y: 0.5}
|
||||
spritePixelsToUnits: 625
|
||||
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: 3
|
||||
buildTarget: DefaultTexturePlatform
|
||||
maxTextureSize: 2048
|
||||
resizeAlgorithm: 0
|
||||
textureFormat: -1
|
||||
textureCompression: 1
|
||||
compressionQuality: 50
|
||||
crunchedCompression: 1
|
||||
allowsAlphaSplitting: 0
|
||||
overridden: 0
|
||||
ignorePlatformSupport: 0
|
||||
androidETC2FallbackOverride: 0
|
||||
forceMaximumCompressionQuality_BC6H_BC7: 0
|
||||
- serializedVersion: 3
|
||||
buildTarget: Standalone
|
||||
maxTextureSize: 1024
|
||||
resizeAlgorithm: 0
|
||||
textureFormat: 29
|
||||
textureCompression: 1
|
||||
compressionQuality: 50
|
||||
crunchedCompression: 0
|
||||
allowsAlphaSplitting: 0
|
||||
overridden: 0
|
||||
ignorePlatformSupport: 0
|
||||
androidETC2FallbackOverride: 0
|
||||
forceMaximumCompressionQuality_BC6H_BC7: 0
|
||||
- serializedVersion: 3
|
||||
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: []
|
||||
outline: []
|
||||
physicsShape: []
|
||||
bones: []
|
||||
spriteID: 5e97eb03825dee720800000000000000
|
||||
internalID: 0
|
||||
vertices: []
|
||||
indices:
|
||||
edges: []
|
||||
weights: []
|
||||
secondaryTextures: []
|
||||
nameFileIdTable: {}
|
||||
mipmapLimitGroupName:
|
||||
pSDRemoveMatte: 0
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
8
Assets/Sprites/SettingsSprites.meta
Normal file
8
Assets/Sprites/SettingsSprites.meta
Normal file
@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: caa69a9f2e4f2204fa32aec6915c6cba
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
BIN
Assets/Sprites/SettingsSprites/стрелка-07.png
Normal file
BIN
Assets/Sprites/SettingsSprites/стрелка-07.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 8.1 KiB |
127
Assets/Sprites/SettingsSprites/стрелка-07.png.meta
Normal file
127
Assets/Sprites/SettingsSprites/стрелка-07.png.meta
Normal file
@ -0,0 +1,127 @@
|
||||
fileFormatVersion: 2
|
||||
guid: e2e62195d0338f2489f389664ec84938
|
||||
TextureImporter:
|
||||
internalIDToNameTable: []
|
||||
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: 1
|
||||
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: 3
|
||||
buildTarget: DefaultTexturePlatform
|
||||
maxTextureSize: 2048
|
||||
resizeAlgorithm: 0
|
||||
textureFormat: -1
|
||||
textureCompression: 1
|
||||
compressionQuality: 50
|
||||
crunchedCompression: 1
|
||||
allowsAlphaSplitting: 0
|
||||
overridden: 0
|
||||
ignorePlatformSupport: 0
|
||||
androidETC2FallbackOverride: 0
|
||||
forceMaximumCompressionQuality_BC6H_BC7: 0
|
||||
- serializedVersion: 3
|
||||
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: 3
|
||||
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: []
|
||||
outline: []
|
||||
physicsShape: []
|
||||
bones: []
|
||||
spriteID: 5e97eb03825dee720800000000000000
|
||||
internalID: 0
|
||||
vertices: []
|
||||
indices:
|
||||
edges: []
|
||||
weights: []
|
||||
secondaryTextures: []
|
||||
nameFileIdTable: {}
|
||||
mipmapLimitGroupName:
|
||||
pSDRemoveMatte: 0
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
BIN
Assets/Sprites/SettingsSprites/стрелка-08.png
Normal file
BIN
Assets/Sprites/SettingsSprites/стрелка-08.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 3.7 KiB |
127
Assets/Sprites/SettingsSprites/стрелка-08.png.meta
Normal file
127
Assets/Sprites/SettingsSprites/стрелка-08.png.meta
Normal file
@ -0,0 +1,127 @@
|
||||
fileFormatVersion: 2
|
||||
guid: aa46adafa643d084abe86ac0f3697446
|
||||
TextureImporter:
|
||||
internalIDToNameTable: []
|
||||
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: 1
|
||||
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: 3
|
||||
buildTarget: DefaultTexturePlatform
|
||||
maxTextureSize: 2048
|
||||
resizeAlgorithm: 0
|
||||
textureFormat: -1
|
||||
textureCompression: 1
|
||||
compressionQuality: 50
|
||||
crunchedCompression: 1
|
||||
allowsAlphaSplitting: 0
|
||||
overridden: 0
|
||||
ignorePlatformSupport: 0
|
||||
androidETC2FallbackOverride: 0
|
||||
forceMaximumCompressionQuality_BC6H_BC7: 0
|
||||
- serializedVersion: 3
|
||||
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: 3
|
||||
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: []
|
||||
outline: []
|
||||
physicsShape: []
|
||||
bones: []
|
||||
spriteID: 5e97eb03825dee720800000000000000
|
||||
internalID: 0
|
||||
vertices: []
|
||||
indices:
|
||||
edges: []
|
||||
weights: []
|
||||
secondaryTextures: []
|
||||
nameFileIdTable: {}
|
||||
mipmapLimitGroupName:
|
||||
pSDRemoveMatte: 0
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
BIN
Assets/Sprites/SettingsSprites/стрелка-09.png
Normal file
BIN
Assets/Sprites/SettingsSprites/стрелка-09.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 7.6 KiB |
Some files were not shown because too many files have changed in this diff Show More
Loading…
x
Reference in New Issue
Block a user