feat: обновлены параметры спрайта и позиционирования для улучшения UI
This commit is contained in:
parent
7e26d6f618
commit
aa358f9794
Binary file not shown.
|
Before Width: | Height: | Size: 2.5 MiB |
@ -1,127 +0,0 @@
|
||||
fileFormatVersion: 2
|
||||
guid: dabfc47e871e05d49b87ab1d70550b0f
|
||||
TextureImporter:
|
||||
internalIDToNameTable: []
|
||||
externalObjects: {}
|
||||
serializedVersion: 12
|
||||
mipmaps:
|
||||
mipMapMode: 0
|
||||
enableMipMap: 1
|
||||
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: 0
|
||||
wrapV: 0
|
||||
wrapW: 0
|
||||
nPOTScale: 1
|
||||
lightmap: 0
|
||||
compressionQuality: 50
|
||||
spriteMode: 0
|
||||
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: 0
|
||||
spriteTessellationDetail: -1
|
||||
textureType: 0
|
||||
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: 0
|
||||
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: Server
|
||||
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:
|
||||
internalID: 0
|
||||
vertices: []
|
||||
indices:
|
||||
edges: []
|
||||
weights: []
|
||||
secondaryTextures: []
|
||||
nameFileIdTable: {}
|
||||
mipmapLimitGroupName:
|
||||
pSDRemoveMatte: 0
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
BIN
Assets/Scenes/test.unity
(Stored with Git LFS)
BIN
Assets/Scenes/test.unity
(Stored with Git LFS)
Binary file not shown.
@ -1,94 +0,0 @@
|
||||
using System.Collections;
|
||||
using UnityEngine;
|
||||
using TMPro;
|
||||
|
||||
public class Coin : MonoBehaviour
|
||||
{
|
||||
public CoinFlipUI flipUI;
|
||||
public TextMeshProUGUI coinText;
|
||||
|
||||
[Header("Flying Coins")]
|
||||
public CoinFlipUI smallCoinPrefab; // ïðåôàá ìîíåòêè (CoinFlipUI)
|
||||
public int spawnCount = 10; // ñêîëüêî ñïàâíèòü
|
||||
public float spawnRadius = 30f; // ðàçáðîñ ñòàðòà
|
||||
public float fallDistance = 100f; // ðàññòîÿíèå âíèç
|
||||
public float duration = 0.8f; // äëèòåëüíîñòü àíèìàöèè
|
||||
|
||||
|
||||
public void FreezeCoin()
|
||||
{
|
||||
if (flipUI != null)
|
||||
flipUI.FreezeCoin();
|
||||
}
|
||||
|
||||
public void UnfreezeCoin()
|
||||
{
|
||||
if (flipUI != null)
|
||||
flipUI.UnfreezeCoin();
|
||||
}
|
||||
|
||||
// Îáíîâëÿåì òåêñò
|
||||
public void ChangeCoinText(string text)
|
||||
{
|
||||
if (coinText != null)
|
||||
coinText.text = text;
|
||||
}
|
||||
|
||||
// -------------------- Àíèìàöèÿ ïîïîëíåíèÿ --------------------
|
||||
public void PlayAddCoinsAnimation()
|
||||
{
|
||||
if (smallCoinPrefab == null || flipUI == null) return;
|
||||
|
||||
RectTransform parentRt = flipUI.GetComponent<RectTransform>();
|
||||
|
||||
for (int i = 0; i < spawnCount; i++)
|
||||
{
|
||||
CoinFlipUI coin = Instantiate(smallCoinPrefab, parentRt.parent); // ñïàâíèì â òîì æå êîíòåéíåðå, ÷òî è flipUI
|
||||
RectTransform rt = coin.GetComponent<RectTransform>();
|
||||
|
||||
// ñòàðòîâàÿ ïîçèöèÿ = ïîçèöèÿ áîëüøîé ìîíåòû
|
||||
rt.position = parentRt.position;
|
||||
|
||||
// óìåíüøàåì ìîíåòêó â 3 ðàçà
|
||||
rt.localScale = smallCoinPrefab.transform.localScale * 0.33f;
|
||||
|
||||
// äîáàâëÿåì ñëó÷àéíîå ñìåùåíèå âîêðóã áîëüøîé ìîíåòû
|
||||
Vector2 randomOffset = Random.insideUnitCircle * spawnRadius;
|
||||
rt.anchoredPosition += randomOffset;
|
||||
|
||||
// çàïóñêàåì àíèìàöèþ
|
||||
StartCoroutine(FlyAndShrinkRoutine(rt));
|
||||
}
|
||||
}
|
||||
|
||||
private IEnumerator FlyAndShrinkRoutine(RectTransform rt)
|
||||
{
|
||||
Vector2 startPos = rt.anchoredPosition;
|
||||
Vector2 endPos = startPos - new Vector2(0, fallDistance);
|
||||
Vector3 startScale = rt.localScale;
|
||||
Vector3 endScale = Vector3.zero;
|
||||
|
||||
float elapsed = 0f;
|
||||
while (elapsed < duration)
|
||||
{
|
||||
elapsed += Time.deltaTime;
|
||||
float t = elapsed / duration;
|
||||
|
||||
rt.anchoredPosition = Vector2.Lerp(startPos, endPos, t);
|
||||
rt.localScale = Vector3.Lerp(startScale, endScale, t);
|
||||
|
||||
// äåëàåì ïðîçðà÷íîñòü
|
||||
var img = rt.GetComponent<UnityEngine.UI.Image>();
|
||||
if (img != null)
|
||||
{
|
||||
var c = img.color;
|
||||
c.a = Mathf.Lerp(1f, 0f, t);
|
||||
img.color = c;
|
||||
}
|
||||
|
||||
yield return null;
|
||||
}
|
||||
|
||||
Destroy(rt.gameObject);
|
||||
}
|
||||
}
|
||||
@ -1,11 +0,0 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 615a287435e2fd8488651baff8ccad22
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@ -1,69 +0,0 @@
|
||||
using UnityEngine;
|
||||
using UnityEngine.UI;
|
||||
|
||||
public class CoinFlipUI : MonoBehaviour
|
||||
{
|
||||
[Header("UI")]
|
||||
public Image coinImage; // ńŕě UI-îáúĺęň ń ęŕđňčíęîé
|
||||
public Sprite headsSprite; // îđ¸ë
|
||||
public Sprite tailsSprite; // đĺřęŕ
|
||||
|
||||
[Header("Spin Settings")]
|
||||
public float spinSpeed = 360f; // ăđŕäóńîâ â ńĺęóíäó
|
||||
public bool autoSpin = true; // ęđóňčňń˙ ďîńňî˙ííî
|
||||
|
||||
private bool showingHeads = true;
|
||||
private Color originalColor;
|
||||
private bool frozen = false; // ôëŕă Ťçŕěîđîçęčť
|
||||
|
||||
private void Awake()
|
||||
{
|
||||
if (coinImage != null)
|
||||
originalColor = coinImage.color; // ńîőđŕí˙ĺě čńőîäíűé öâĺň
|
||||
}
|
||||
|
||||
/// <summary>Äĺëŕĺě ěîíĺňó ńĺđîé č îńňŕíŕâëčâŕĺě âđŕůĺíčĺ</summary>
|
||||
public void FreezeCoin()
|
||||
{
|
||||
if (coinImage != null)
|
||||
{
|
||||
coinImage.color = Color.grey;
|
||||
coinImage.sprite = headsSprite; // âńĺăäŕ ďîęŕçűâŕĺě ďĺđâűé ńďđŕéň
|
||||
|
||||
// ńáđŕńűâŕĺě âđŕůĺíčĺ, ÷ňîáű ěîíĺňŕ ńěîňđĺëŕ "âďĺđ¸ä"
|
||||
coinImage.rectTransform.localEulerAngles = Vector3.zero;
|
||||
}
|
||||
frozen = true;
|
||||
}
|
||||
|
||||
/// <summary>Âîçâđŕůŕĺě ěîíĺňó â íîđěŕëüíîĺ ńîńňî˙íčĺ č âęëţ÷ŕĺě âđŕůĺíčĺ</summary>
|
||||
public void UnfreezeCoin()
|
||||
{
|
||||
if (coinImage != null)
|
||||
coinImage.color = originalColor;
|
||||
|
||||
frozen = false;
|
||||
}
|
||||
|
||||
void Update()
|
||||
{
|
||||
if (frozen || !autoSpin) return;
|
||||
|
||||
// ęđóňčě ěîíĺňęó
|
||||
coinImage.rectTransform.Rotate(Vector3.up * spinSpeed * Time.deltaTime);
|
||||
|
||||
float yAngle = coinImage.rectTransform.localEulerAngles.y;
|
||||
|
||||
// ěĺí˙ĺě ńďđŕéň íŕ îáîđîňíîé ńňîđîíĺ
|
||||
if (yAngle > 90f && yAngle < 270f && showingHeads)
|
||||
{
|
||||
coinImage.sprite = tailsSprite;
|
||||
showingHeads = false;
|
||||
}
|
||||
else if ((yAngle <= 90f || yAngle >= 270f) && !showingHeads)
|
||||
{
|
||||
coinImage.sprite = headsSprite;
|
||||
showingHeads = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1,11 +0,0 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 2937e80c8d6174347ae0018b6d0b0c3b
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@ -1,73 +0,0 @@
|
||||
using UnityEngine;
|
||||
|
||||
/// <summary>
|
||||
/// Îòâå÷àåò òîëüêî çà îòîáðàæåíèå è îáíîâëåíèå UI ìîíåò
|
||||
/// </summary>
|
||||
public class CoinUI : MonoBehaviour
|
||||
{
|
||||
[SerializeField] private int playerId;
|
||||
[SerializeField] private Coin coin;
|
||||
|
||||
private int lastCoins;
|
||||
private bool eventsSubscribed;
|
||||
|
||||
private void OnEnable()
|
||||
{
|
||||
ComWrapper.OnInitialize += Subscribe;
|
||||
|
||||
if (!eventsSubscribed && (ComWrapper.onCoinAdded != null || ComWrapper.onCoinRemoved != null))
|
||||
Subscribe();
|
||||
}
|
||||
|
||||
private void OnDisable()
|
||||
{
|
||||
if (eventsSubscribed)
|
||||
{
|
||||
if (ComWrapper.onCoinAdded != null) ComWrapper.onCoinAdded.RemoveListener(HandleCoinsChanged);
|
||||
if (ComWrapper.onCoinRemoved != null) ComWrapper.onCoinRemoved.RemoveListener(HandleCoinsChanged);
|
||||
eventsSubscribed = false;
|
||||
}
|
||||
|
||||
ComWrapper.OnInitialize -= Subscribe;
|
||||
}
|
||||
|
||||
private void Subscribe()
|
||||
{
|
||||
if (eventsSubscribed) return;
|
||||
|
||||
if (ComWrapper.onCoinAdded != null) ComWrapper.onCoinAdded.AddListener(HandleCoinsChanged);
|
||||
if (ComWrapper.onCoinRemoved != null) ComWrapper.onCoinRemoved.AddListener(HandleCoinsChanged);
|
||||
|
||||
lastCoins = ComWrapper.GetPlayerCredits(playerId);
|
||||
eventsSubscribed = true;
|
||||
}
|
||||
|
||||
private void Start()
|
||||
{
|
||||
int current = ComWrapper.GetPlayerCredits(playerId);
|
||||
lastCoins = current;
|
||||
|
||||
if (coin != null)
|
||||
{
|
||||
coin.ChangeCoinText($"{current}");
|
||||
if (current == 0) coin.FreezeCoin();
|
||||
else coin.UnfreezeCoin();
|
||||
}
|
||||
}
|
||||
|
||||
private void HandleCoinsChanged(int playerID, int newAmount)
|
||||
{
|
||||
if (coin == null || playerID != playerId) return;
|
||||
|
||||
coin.ChangeCoinText($"{newAmount}");
|
||||
|
||||
if (newAmount == 0) coin.FreezeCoin();
|
||||
else coin.UnfreezeCoin();
|
||||
|
||||
if (newAmount > lastCoins)
|
||||
coin.PlayAddCoinsAnimation();
|
||||
|
||||
lastCoins = newAmount;
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,3 +0,0 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 0b362969ae104ca7bda6aadc36f41dbd
|
||||
timeCreated: 1770037304
|
||||
@ -1,297 +0,0 @@
|
||||
using System.Collections;
|
||||
using UnityEngine;
|
||||
using UnityEngine.UI;
|
||||
using TMPro;
|
||||
|
||||
public class EnemyCardController : MonoBehaviour
|
||||
{
|
||||
[Header("UI Elements")]
|
||||
public Image avatarImage;
|
||||
public Animator avatarAnimator;
|
||||
public TMP_Text nicknameText;
|
||||
public TMP_Text dialogueText;
|
||||
public RectTransform dialoguePanel;
|
||||
|
||||
[Header("Settings")]
|
||||
public float typingSpeed = 0.05f;
|
||||
public float panelExpandWidth = 300f;
|
||||
public float panelExpandSpeed = 5f;
|
||||
|
||||
[Header("Animation names")]
|
||||
public string idleAnimationName = "Idle_bot_1";
|
||||
public string transitionIn = "forvard_bot";
|
||||
public string transitionOut = "back_bot";
|
||||
|
||||
private Coroutine panelAnimCoroutine;
|
||||
private Coroutine textTypingCoroutine;
|
||||
private Vector2 dialogueOriginalPos;
|
||||
private WaitForSeconds cachedTypingWait;
|
||||
private System.Collections.Generic.HashSet<string> availableStates = new System.Collections.Generic.HashSet<string>();
|
||||
|
||||
private void Awake()
|
||||
{
|
||||
if (dialoguePanel != null)
|
||||
dialogueOriginalPos = dialoguePanel.anchoredPosition;
|
||||
|
||||
cachedTypingWait = new WaitForSeconds(typingSpeed);
|
||||
ValidateReferences();
|
||||
}
|
||||
|
||||
private void OnValidate()
|
||||
{
|
||||
ValidateReferences();
|
||||
}
|
||||
|
||||
private void ValidateReferences()
|
||||
{
|
||||
if (avatarImage == null) Debug.LogWarning($"[{name}] avatarImage íå íàçíà÷åí!", this);
|
||||
if (nicknameText == null) Debug.LogWarning($"[{name}] nicknameText íå íàçíà÷åí!", this);
|
||||
if (dialogueText == null) Debug.LogWarning($"[{name}] dialogueText íå íàçíà÷åí!", this);
|
||||
if (dialoguePanel == null) Debug.LogWarning($"[{name}] dialoguePanel íå íàçíà÷åí!", this);
|
||||
}
|
||||
|
||||
private void OnDisable()
|
||||
{
|
||||
StopAllAnimations();
|
||||
ResetUIState();
|
||||
}
|
||||
|
||||
public void SetEnemy(EnemyData enemy)
|
||||
{
|
||||
if (enemy == null)
|
||||
{
|
||||
Debug.LogWarning($"[{name}] SetEnemy: enemy is null!");
|
||||
return;
|
||||
}
|
||||
|
||||
if (nicknameText != null)
|
||||
nicknameText.text = enemy.nickname;
|
||||
|
||||
SetupAnimatorOrSprite(enemy);
|
||||
ResetUIState();
|
||||
|
||||
// Óñòàíàâëèâàåì ïîðÿäîê ïàíåëè (òîëüêî êîãäà îáúåêò àêòèâåí)
|
||||
if (dialoguePanel != null && gameObject.activeInHierarchy)
|
||||
dialoguePanel.SetSiblingIndex(0);
|
||||
}
|
||||
|
||||
private void SetupAnimatorOrSprite(EnemyData enemy)
|
||||
{
|
||||
availableStates.Clear();
|
||||
|
||||
if (enemy.animatorOverride != null && avatarAnimator != null)
|
||||
{
|
||||
avatarAnimator.runtimeAnimatorController = enemy.animatorOverride;
|
||||
avatarAnimator.enabled = true;
|
||||
|
||||
// Êýøèðóåì äîñòóïíûå êëèïû îäèí ðàç
|
||||
var overrides = new System.Collections.Generic.List<System.Collections.Generic.KeyValuePair<AnimationClip, AnimationClip>>();
|
||||
enemy.animatorOverride.GetOverrides(overrides);
|
||||
|
||||
foreach (var pair in overrides)
|
||||
{
|
||||
if (pair.Value != null) // Åñòü ïåðåîïðåäåë¸ííûé êëèï
|
||||
availableStates.Add(pair.Key.name);
|
||||
}
|
||||
|
||||
SetEmotion(idleAnimationName);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (avatarAnimator != null)
|
||||
avatarAnimator.enabled = false;
|
||||
|
||||
if (enemy.characterSprite != null && avatarImage != null)
|
||||
avatarImage.sprite = enemy.characterSprite;
|
||||
}
|
||||
}
|
||||
|
||||
private void ResetUIState()
|
||||
{
|
||||
if (dialogueText != null)
|
||||
dialogueText.text = "";
|
||||
|
||||
if (dialoguePanel != null)
|
||||
{
|
||||
dialoguePanel.anchoredPosition = dialogueOriginalPos;
|
||||
}
|
||||
}
|
||||
|
||||
private void StopAllAnimations()
|
||||
{
|
||||
if (panelAnimCoroutine != null)
|
||||
{
|
||||
StopCoroutine(panelAnimCoroutine);
|
||||
panelAnimCoroutine = null;
|
||||
}
|
||||
|
||||
if (textTypingCoroutine != null)
|
||||
{
|
||||
StopCoroutine(textTypingCoroutine);
|
||||
textTypingCoroutine = null;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Îòêðûâàåò êàðòî÷êó ñ àíèìàöèåé, âûçûâàåò callback êîãäà îòêðûëàñü
|
||||
/// </summary>
|
||||
public void ShowCard(string emotionState, System.Action onShown = null)
|
||||
{
|
||||
if (panelAnimCoroutine != null)
|
||||
StopCoroutine(panelAnimCoroutine);
|
||||
|
||||
panelAnimCoroutine = StartCoroutine(ShowCardCoroutine(emotionState, onShown));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Çàêðûâàåò êàðòî÷êó ñ àíèìàöèåé, âûçûâàåò callback êîãäà çàêðûëàñü
|
||||
/// </summary>
|
||||
public void HideCard(System.Action onHidden = null)
|
||||
{
|
||||
if (panelAnimCoroutine != null)
|
||||
StopCoroutine(panelAnimCoroutine);
|
||||
|
||||
panelAnimCoroutine = StartCoroutine(HideCardCoroutine(onHidden));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Ïå÷àòàåò òåêñò ïîñèìâîëüíî, âûçûâàåò callback ïî îêîí÷àíèè
|
||||
/// </summary>
|
||||
public void TypeText(string text, System.Action onComplete = null, bool skipSizePreparation = false)
|
||||
{
|
||||
if (textTypingCoroutine != null)
|
||||
StopCoroutine(textTypingCoroutine);
|
||||
|
||||
textTypingCoroutine = StartCoroutine(TypeTextCoroutine(text, onComplete, skipSizePreparation));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Ìãíîâåííî óñòàíàâëèâàåò òåêñò áåç àíèìàöèè ïå÷àòè
|
||||
/// </summary>
|
||||
public void SetTextImmediate(string text)
|
||||
{
|
||||
if (textTypingCoroutine != null)
|
||||
{
|
||||
StopCoroutine(textTypingCoroutine);
|
||||
textTypingCoroutine = null;
|
||||
}
|
||||
|
||||
if (dialogueText != null)
|
||||
dialogueText.text = text;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Ïîäãîòàâëèâàåò ðàçìåð òåêñòà çàðàíåå (÷òîáû èçáåæàòü "áëèêà" ïðè îòêðûòèè ïàíåëè)
|
||||
/// </summary>
|
||||
public IEnumerator PrepareTextSizeAsync(string text)
|
||||
{
|
||||
yield return PrepareTextSize(text);
|
||||
}
|
||||
|
||||
private IEnumerator ShowCardCoroutine(string emotionState, System.Action onShown)
|
||||
{
|
||||
if (dialoguePanel == null) yield break;
|
||||
|
||||
SetEmotion(transitionIn);
|
||||
|
||||
Vector2 hiddenPos = dialogueOriginalPos;
|
||||
Vector2 shownPos = hiddenPos + new Vector2(panelExpandWidth, 0);
|
||||
|
||||
float t = 0f;
|
||||
while (t < 1f)
|
||||
{
|
||||
t += Time.deltaTime * panelExpandSpeed;
|
||||
dialoguePanel.anchoredPosition = Vector2.Lerp(hiddenPos, shownPos, t);
|
||||
yield return null;
|
||||
}
|
||||
|
||||
dialoguePanel.anchoredPosition = shownPos;
|
||||
SetEmotion(emotionState);
|
||||
|
||||
onShown?.Invoke();
|
||||
}
|
||||
|
||||
private IEnumerator HideCardCoroutine(System.Action onHidden)
|
||||
{
|
||||
if (dialoguePanel == null) yield break;
|
||||
|
||||
SetEmotion(transitionOut);
|
||||
|
||||
if (dialogueText != null)
|
||||
dialogueText.text = "";
|
||||
|
||||
Vector2 hiddenPos = dialogueOriginalPos;
|
||||
Vector2 shownPos = hiddenPos + new Vector2(panelExpandWidth, 0);
|
||||
|
||||
float t = 0f;
|
||||
while (t < 1f)
|
||||
{
|
||||
t += Time.deltaTime * panelExpandSpeed;
|
||||
dialoguePanel.anchoredPosition = Vector2.Lerp(shownPos, hiddenPos, t);
|
||||
yield return null;
|
||||
}
|
||||
|
||||
dialoguePanel.anchoredPosition = hiddenPos;
|
||||
SetEmotion(idleAnimationName);
|
||||
|
||||
onHidden?.Invoke();
|
||||
}
|
||||
|
||||
private IEnumerator TypeTextCoroutine(string text, System.Action onComplete, bool skipSizePreparation)
|
||||
{
|
||||
if (dialogueText == null) yield break;
|
||||
|
||||
// Ïîäãîòîâêà ðàçìåðà øðèôòà (ïðîïóñêàåì åñëè óæå ñäåëàíî)
|
||||
if (!skipSizePreparation)
|
||||
{
|
||||
yield return PrepareTextSize(text);
|
||||
}
|
||||
|
||||
// Ïå÷àòü ïî ñèìâîëàì ÷åðåç maxVisibleCharacters (îïòèìèçàöèÿ)
|
||||
dialogueText.text = text;
|
||||
dialogueText.ForceMeshUpdate();
|
||||
|
||||
int totalChars = dialogueText.textInfo.characterCount;
|
||||
dialogueText.maxVisibleCharacters = 0;
|
||||
|
||||
for (int i = 0; i <= totalChars; i++)
|
||||
{
|
||||
dialogueText.maxVisibleCharacters = i;
|
||||
yield return cachedTypingWait;
|
||||
}
|
||||
|
||||
onComplete?.Invoke();
|
||||
}
|
||||
|
||||
private IEnumerator PrepareTextSize(string text)
|
||||
{
|
||||
if (dialogueText == null) yield break;
|
||||
|
||||
dialogueText.enableWordWrapping = true;
|
||||
dialogueText.overflowMode = TextOverflowModes.Overflow;
|
||||
dialogueText.text = text;
|
||||
dialogueText.enableAutoSizing = true;
|
||||
dialogueText.fontSizeMin = 5;
|
||||
|
||||
yield return null; // Æä¸ì êàäð äëÿ ðàñ÷¸òà
|
||||
|
||||
float finalFontSize = dialogueText.fontSize;
|
||||
dialogueText.enableAutoSizing = false;
|
||||
dialogueText.fontSize = finalFontSize;
|
||||
dialogueText.text = "";
|
||||
}
|
||||
|
||||
|
||||
public void SetEmotion(string stateName)
|
||||
{
|
||||
if (avatarAnimator == null || !avatarAnimator.enabled || string.IsNullOrEmpty(stateName))
|
||||
return;
|
||||
|
||||
if (availableStates.Contains(stateName))
|
||||
avatarAnimator.Play(stateName);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
@ -1,11 +0,0 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 19ed6f95566642b4d996b18b1d8d8aa9
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@ -1,112 +0,0 @@
|
||||
using UnityEngine;
|
||||
using System;
|
||||
|
||||
[CreateAssetMenu(fileName = "NewEnemyData", menuName = "Enemies/EnemyData")]
|
||||
public class EnemyData : ScriptableObject
|
||||
{
|
||||
public string nickname;
|
||||
|
||||
|
||||
|
||||
|
||||
[Header("Àíèìàöèè ïåðñîíàæà")]
|
||||
public AnimatorOverrideController animatorOverride; // äëÿ ïîêàäðîâîé àíèìàöèè
|
||||
public Sprite characterSprite; // òåêóùèé/íåéòðàëüíûé ñïðàéò (fallback)
|
||||
|
||||
[Header("Îçâó÷êà ïîáåäû èãðîêà")]
|
||||
public AudioClip[] playerVictory;
|
||||
[Header("Îçâó÷êà ïîáåäû áîòà")]
|
||||
public AudioClip[] playerDefeat;
|
||||
|
||||
[Header("Ôðàçû äëÿ äèàëîãà")]
|
||||
|
||||
public DialogueLine[] dialogues;
|
||||
|
||||
[Header("Ñîáûòèéíûå äèàëîãè")]
|
||||
public DialogueLine[] onPlayerHit; // Èãðîê ïîïàë
|
||||
public DialogueLine[] onPlayerMiss; // Èãðîê ïðîìàçàë
|
||||
public DialogueLine[] onBotHit; // Áîò ïîïàë
|
||||
public DialogueLine[] onBotMiss; // Áîò ïðîìàçàë
|
||||
public DialogueLine[] onPlayerShipDestroyed; // Êîðàáëü èãðîêà óíè÷òîæåí
|
||||
public DialogueLine[] onBotShipDestroyed; // Êîðàáëü áîòà óíè÷òîæåí
|
||||
|
||||
// Âñïîìîãàòåëüíûé ìåòîä äëÿ ïîëó÷åíèÿ ñëó÷àéíîé ôðàçû èç êàòåãîðèè
|
||||
public DialogueLine? GetRandomDialogue(DialogueEventType eventType)
|
||||
{
|
||||
DialogueLine[] sourceArray = null;
|
||||
switch (eventType)
|
||||
{
|
||||
case DialogueEventType.PlayerHit: sourceArray = onPlayerHit; break;
|
||||
case DialogueEventType.PlayerMiss: sourceArray = onPlayerMiss; break;
|
||||
case DialogueEventType.BotHit: sourceArray = onBotHit; break;
|
||||
case DialogueEventType.BotMiss: sourceArray = onBotMiss; break;
|
||||
case DialogueEventType.PlayerShipDestroyed: sourceArray = onPlayerShipDestroyed; break;
|
||||
case DialogueEventType.BotShipDestroyed: sourceArray = onBotShipDestroyed; break;
|
||||
}
|
||||
|
||||
if (sourceArray != null && sourceArray.Length > 0)
|
||||
{
|
||||
return sourceArray[UnityEngine.Random.Range(0, sourceArray.Length)];
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public enum DialogueEventType
|
||||
{
|
||||
PlayerHit,
|
||||
PlayerMiss,
|
||||
BotHit,
|
||||
BotMiss,
|
||||
PlayerShipDestroyed,
|
||||
BotShipDestroyed
|
||||
}
|
||||
|
||||
// Enum äëÿ èì¸í ñîñòîÿíèé àíèìàòîðà
|
||||
public enum AnimationName
|
||||
{
|
||||
None,
|
||||
TalkBot1,
|
||||
TalkBot2,
|
||||
TalkBot3,
|
||||
TalkBot4,
|
||||
AngerBot1,
|
||||
AngerBot2,
|
||||
LaughterBot1,
|
||||
BackBot,
|
||||
ForwardBot
|
||||
}
|
||||
|
||||
[System.Serializable]
|
||||
public struct DialogueLine
|
||||
{
|
||||
[TextArea(2, 5)]
|
||||
public string text;
|
||||
|
||||
// Òåïåðü èñïîëüçóåì enum âìåñòî ñòðîêè — â èíñïåêòîðå áóäåò âûïàäàþùèé ñïèñîê
|
||||
public AnimationName animationName; // íàïðèìåð AnimationName.TalkBot1
|
||||
|
||||
public AudioClip voiceClip;
|
||||
}
|
||||
|
||||
// Âñïîìîãàòåëüíûé êëàññ, êîòîðûé äà¸ò ñòðîêîâîå èìÿ ñîñòîÿíèÿ àíèìàòîðà äëÿ êàæäîãî enum-÷ëåíà
|
||||
public static class AnimationNameExtensions
|
||||
{
|
||||
public static string ToStateName(this AnimationName name)
|
||||
{
|
||||
switch (name)
|
||||
{
|
||||
case AnimationName.TalkBot1: return "talk_bot_1";
|
||||
case AnimationName.TalkBot2: return "talk_bot_2";
|
||||
case AnimationName.TalkBot3: return "talk_bot_3";
|
||||
case AnimationName.TalkBot4: return "talk_bot_4";
|
||||
case AnimationName.AngerBot1: return "anger_bot_1";
|
||||
case AnimationName.AngerBot2: return "anger_bot_2";
|
||||
case AnimationName.LaughterBot1: return "laughter_bot_1";
|
||||
case AnimationName.BackBot: return "back_bot";
|
||||
case AnimationName.ForwardBot: return "forward_bot";
|
||||
default: return string.Empty;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1,11 +0,0 @@
|
||||
fileFormatVersion: 2
|
||||
guid: aad3df3b54a3fd64d8288b172c35ad49
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@ -1,271 +0,0 @@
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
|
||||
public class EnemyManager : MonoBehaviour
|
||||
{
|
||||
[Header("Ñïèñîê âðàãîâ")]
|
||||
public EnemyData[] enemies;
|
||||
|
||||
[Header("UI êîíòðîëëåð êàðòî÷êè")]
|
||||
public EnemyCardController cardController;
|
||||
|
||||
[Header("Settings")]
|
||||
public float dialogueHoldTime = 1f;
|
||||
|
||||
private int currentIndex = 0;
|
||||
private int playerId = 1;
|
||||
private Coroutine currentDialogueCoroutine;
|
||||
private bool isDialoguePlaying = false;
|
||||
|
||||
// Îòñëåæèâàíèå èñïîëüçîâàííûõ ðåïëèê äëÿ êàæäîãî òèïà ñîáûòèÿ
|
||||
private Dictionary<DialogueEventType, List<int>> usedDialogueIndices = new Dictionary<DialogueEventType, List<int>>();
|
||||
|
||||
private void Start()
|
||||
{
|
||||
var player = gameObject.GetComponentInParent<Player>();
|
||||
if (player != null)
|
||||
playerId = player.PlayerId;
|
||||
else
|
||||
Debug.LogWarning($"[{name}] Player íå íàéäåí â ðîäèòåëÿõ!");
|
||||
}
|
||||
|
||||
public void SetEnemy(int index)
|
||||
{
|
||||
if (enemies == null || index < 0 || index >= enemies.Length)
|
||||
{
|
||||
Debug.LogWarning($"[{name}] SetEnemy: invalid index {index}");
|
||||
return;
|
||||
}
|
||||
|
||||
if (!cardController.gameObject.activeSelf)
|
||||
cardController.gameObject.SetActive(true);
|
||||
|
||||
currentIndex = index;
|
||||
cardController.SetEnemy(enemies[index]);
|
||||
isDialoguePlaying = false;
|
||||
|
||||
// Ñáðàñûâàåì èñòîðèþ èñïîëüçîâàííûõ ðåïëèê ïðè ñìåíå âðàãà
|
||||
usedDialogueIndices.Clear();
|
||||
}
|
||||
|
||||
public void SetEnemyPlayer()
|
||||
{
|
||||
// Ïðîôèëè èãðîêîâ - ýòî ïîñëåäíèå 2 ýëåìåíòà â ìàññèâå enemies
|
||||
// playerId = 1 -> enemies[Length-2], playerId = 2 -> enemies[Length-1]
|
||||
if (enemies == null || enemies.Length < 2)
|
||||
{
|
||||
Debug.LogWarning($"[{name}] SetEnemyPlayer: íåäîñòàòî÷íî âðàãîâ â ìàññèâå äëÿ ïðîôèëåé èãðîêîâ!");
|
||||
cardController.gameObject.SetActive(false);
|
||||
return;
|
||||
}
|
||||
|
||||
int playerProfileIndex = enemies.Length - (3 - playerId); // playerId 1 -> -2, playerId 2 -> -1
|
||||
|
||||
if (playerProfileIndex < 0 || playerProfileIndex >= enemies.Length)
|
||||
{
|
||||
Debug.LogWarning($"[{name}] SetEnemyPlayer: íåêîððåêòíûé èíäåêñ ïðîôèëÿ èãðîêà {playerProfileIndex}");
|
||||
cardController.gameObject.SetActive(false);
|
||||
return;
|
||||
}
|
||||
|
||||
currentIndex = playerProfileIndex;
|
||||
|
||||
// Ñêðûâàåì êàðòî÷êó (èãðîê íå ïîêàçûâàåò UI)
|
||||
cardController.gameObject.SetActive(false);
|
||||
|
||||
isDialoguePlaying = false;
|
||||
|
||||
// Ñáðàñûâàåì èñòîðèþ èñïîëüçîâàííûõ ðåïëèê
|
||||
usedDialogueIndices.Clear();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Ïîêàçûâàåò äèàëîã ñ êàðòî÷êîé: îòêðûâàåò ? ãîâîðèò ? çàêðûâàåò
|
||||
/// Åñëè êàðòî÷êà íåàêòèâíà - ïðîñòî èãðàåò çâóê
|
||||
/// </summary>
|
||||
public void ShowDialogueWithCard(DialogueLine line)
|
||||
{
|
||||
// Åñëè êàðòî÷êà íåàêòèâíà - ïðîñòî èãðàåì çâóê
|
||||
if (cardController == null || !cardController.gameObject.activeInHierarchy)
|
||||
{
|
||||
PlayVoiceOnly(line.voiceClip);
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
if (currentDialogueCoroutine != null)
|
||||
StopCoroutine(currentDialogueCoroutine);
|
||||
|
||||
currentDialogueCoroutine = StartCoroutine(DialogueWithCardSequence(line));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Ïðîèãðûâàåò òîëüêî çâóê áåç êàðòî÷êè
|
||||
/// </summary>
|
||||
public void PlayVoiceOnly(AudioClip clip)
|
||||
{
|
||||
if (clip != null && SoundManager.Instance != null)
|
||||
{
|
||||
SoundManager.Instance.PlayVoice(playerId, clip);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Ïîêàçûâàåò òåêñò íà óæå îòêðûòîé êàðòî÷êå (áåç àíèìàöèè îòêðûòèÿ/çàêðûòèÿ)
|
||||
/// </summary>
|
||||
public void ShowTextOnly(string text, string emotion = null)
|
||||
{
|
||||
if (!string.IsNullOrEmpty(emotion))
|
||||
cardController.SetEmotion(emotion);
|
||||
|
||||
cardController.TypeText(text);
|
||||
}
|
||||
|
||||
private IEnumerator DialogueWithCardSequence(DialogueLine line)
|
||||
{
|
||||
isDialoguePlaying = true;
|
||||
|
||||
// 1. Ïîäãîòàâëèâàåì ðàçìåð òåêñòà ÄÎ îòêðûòèÿ ïàíåëè (÷òîáû íå áûëî "áëèêà")
|
||||
yield return cardController.PrepareTextSizeAsync(line.text);
|
||||
|
||||
// 2. Îòêðûâàåì êàðòî÷êó ñ ýìîöèåé ïåðåõîäà
|
||||
bool cardOpened = false;
|
||||
cardController.ShowCard(line.animationName.ToStateName(), () => cardOpened = true);
|
||||
|
||||
// Æä¸ì, ïîêà êàðòî÷êà îòêðîåòñÿ
|
||||
yield return new WaitUntil(() => cardOpened);
|
||||
|
||||
// 3. Èãðàåì çâóê
|
||||
if (line.voiceClip != null && SoundManager.Instance != null)
|
||||
{
|
||||
SoundManager.Instance.PlayVoice(playerId, line.voiceClip);
|
||||
}
|
||||
|
||||
// 4. Ïå÷àòàåì òåêñò (ðàçìåð óæå ïîäãîòîâëåí)
|
||||
bool textComplete = false;
|
||||
cardController.TypeText(line.text, () => textComplete = true, skipSizePreparation: true);
|
||||
|
||||
// Æä¸ì, ïîêà òåêñò íàïå÷àòàåòñÿ
|
||||
yield return new WaitUntil(() => textComplete);
|
||||
|
||||
// 4. Äåðæèì òåêñò íåìíîãî
|
||||
yield return new WaitForSeconds(dialogueHoldTime);
|
||||
|
||||
// 5. Çàêðûâàåì êàðòî÷êó
|
||||
bool cardClosed = false;
|
||||
cardController.HideCard(() => cardClosed = true);
|
||||
|
||||
yield return new WaitUntil(() => cardClosed);
|
||||
|
||||
isDialoguePlaying = false;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Âûçûâàåò äèàëîã ðåàêöèè íà ñîáûòèå (ñ êàðòî÷êîé)
|
||||
/// Âûáèðàåò ðåïëèêó êîòîðàÿ åù¸ íå èñïîëüçîâàëàñü, ïîêà âñå íå êîí÷àòñÿ
|
||||
/// </summary>
|
||||
public void TriggerEventReaction(DialogueEventType eventType)
|
||||
{
|
||||
if (enemies == null || currentIndex < 0 || currentIndex >= enemies.Length)
|
||||
return;
|
||||
|
||||
if(isDialoguePlaying) return;
|
||||
|
||||
var enemy = enemies[currentIndex];
|
||||
DialogueLine? line = GetNonRepeatingDialogue(enemy, eventType);
|
||||
|
||||
if (line.HasValue)
|
||||
{
|
||||
ShowDialogueWithCard(line.Value);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Ïîëó÷àåò ñëó÷àéíóþ ðåïëèêó êîòîðàÿ åù¸ íå èñïîëüçîâàëàñü äëÿ äàííîãî òèïà ñîáûòèÿ
|
||||
/// </summary>
|
||||
private DialogueLine? GetNonRepeatingDialogue(EnemyData enemy, DialogueEventType eventType)
|
||||
{
|
||||
if (enemy == null)
|
||||
return null;
|
||||
|
||||
// Ïîëó÷àåì íóæíûé ìàññèâ ðåïëèê ïî òèïó ñîáûòèÿ
|
||||
DialogueLine[] sourceArray = null;
|
||||
switch (eventType)
|
||||
{
|
||||
case DialogueEventType.PlayerHit: sourceArray = enemy.onPlayerHit; break;
|
||||
case DialogueEventType.PlayerMiss: sourceArray = enemy.onPlayerMiss; break;
|
||||
case DialogueEventType.BotHit: sourceArray = enemy.onBotHit; break;
|
||||
case DialogueEventType.BotMiss: sourceArray = enemy.onBotMiss; break;
|
||||
case DialogueEventType.PlayerShipDestroyed: sourceArray = enemy.onPlayerShipDestroyed; break;
|
||||
case DialogueEventType.BotShipDestroyed: sourceArray = enemy.onBotShipDestroyed; break;
|
||||
}
|
||||
|
||||
if (sourceArray == null || sourceArray.Length == 0)
|
||||
return null;
|
||||
|
||||
// Èíèöèàëèçèðóåì ñïèñîê èñïîëüçîâàííûõ ðåïëèê äëÿ ýòîãî òèïà ñîáûòèÿ åñëè íóæíî
|
||||
if (!usedDialogueIndices.ContainsKey(eventType))
|
||||
{
|
||||
usedDialogueIndices[eventType] = new List<int>();
|
||||
}
|
||||
|
||||
var usedList = usedDialogueIndices[eventType];
|
||||
|
||||
// Ñîçäà¸ì ñïèñîê íåèñïîëüçîâàííûõ èíäåêñîâ
|
||||
var unusedIndices = new List<int>();
|
||||
for (int i = 0; i < sourceArray.Length; i++)
|
||||
{
|
||||
if (!usedList.Contains(i))
|
||||
unusedIndices.Add(i);
|
||||
}
|
||||
|
||||
// Åñëè âñå ðåïëèêè èñïîëüçîâàíû - ñáðàñûâàåì è íà÷èíàåì çàíîâî
|
||||
if (unusedIndices.Count == 0)
|
||||
{
|
||||
usedList.Clear();
|
||||
for (int i = 0; i < sourceArray.Length; i++)
|
||||
{
|
||||
unusedIndices.Add(i);
|
||||
}
|
||||
}
|
||||
|
||||
// Âûáèðàåì ñëó÷àéíûé íåèñïîëüçîâàííûé èíäåêñ
|
||||
int randomIndex = unusedIndices[Random.Range(0, unusedIndices.Count)];
|
||||
usedList.Add(randomIndex);
|
||||
|
||||
return sourceArray[randomIndex];
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Ðåàêöèÿ íà êîíåö èãðû (òîëüêî çâóê, áåç êàðòî÷êè)
|
||||
/// </summary>
|
||||
public void TriggerEndGameReaction(bool playerWon)
|
||||
{
|
||||
if (enemies == null || enemies.Length == 0) return;
|
||||
if (currentIndex < 0 || currentIndex >= enemies.Length) return;
|
||||
isDialoguePlaying = true;
|
||||
|
||||
var enemy = enemies[currentIndex];
|
||||
var clips = playerWon ? enemy.playerVictory : enemy.playerDefeat;
|
||||
|
||||
if (clips == null || clips.Length == 0) return;
|
||||
|
||||
// Îñòàíàâëèâàåì ãîëîñîâîé êàíàë òåêóùåãî èãðîêà, çàòåì ïðîèãðûâàåì ôèíàëüíóþ ôðàçó
|
||||
if (SoundManager.Instance != null)
|
||||
{
|
||||
SoundManager.Instance.StopVoice(playerId);
|
||||
}
|
||||
Debug.Log(clips[0].name);
|
||||
|
||||
PlayVoiceOnly(clips[Random.Range(0, clips.Length)]);
|
||||
}
|
||||
|
||||
public EnemyData GetCurrentEnemy()
|
||||
{
|
||||
if (enemies == null || currentIndex < 0 || currentIndex >= enemies.Length)
|
||||
return null;
|
||||
|
||||
return enemies[currentIndex];
|
||||
}
|
||||
}
|
||||
@ -1,11 +0,0 @@
|
||||
fileFormatVersion: 2
|
||||
guid: ab306eb3313a66f4291adfc45803dcb7
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@ -1,13 +0,0 @@
|
||||
using UnityEngine;
|
||||
using UnityEngine.UI;
|
||||
|
||||
public class GameOver : MonoBehaviour
|
||||
{
|
||||
[SerializeField] private Sprite[] sprites;
|
||||
public Image image; // Ýòî Image íà ñöåíå, êóäà âñòàâèòñÿ ñïðàéò
|
||||
|
||||
public void GameOverSwitch(bool victory)
|
||||
{
|
||||
image.sprite = victory ? sprites[0] : sprites[1];
|
||||
}
|
||||
}
|
||||
@ -1,11 +0,0 @@
|
||||
fileFormatVersion: 2
|
||||
guid: f543ea72d7834b645bd21c1abd0852d5
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@ -1,102 +0,0 @@
|
||||
using UnityEngine;
|
||||
using UnityEngine.UI;
|
||||
using TMPro;
|
||||
|
||||
/// <summary>
|
||||
/// Îòâå÷àåò çà îòîáðàæåíèå ýêðàíà GameOver è îáíîâëåíèå êíîïîê
|
||||
/// </summary>
|
||||
public class GameOverUI : MonoBehaviour
|
||||
{
|
||||
[SerializeField] private int playerId;
|
||||
[SerializeField] private GameManager gameManager;
|
||||
|
||||
[Header("UI Elements")]
|
||||
[SerializeField] private Button replayButton;
|
||||
[SerializeField] private Button continueButton;
|
||||
[SerializeField] private TextMeshProUGUI resultText;
|
||||
[SerializeField] private GameObject uiParticle;
|
||||
[SerializeField] private GameOver gameOverStatusImage;
|
||||
|
||||
public void Show(bool isWin, bool isBotGame)
|
||||
{
|
||||
if (uiParticle != null)
|
||||
uiParticle.SetActive(isWin);
|
||||
|
||||
if (resultText != null)
|
||||
{
|
||||
resultText.text = isWin ? "Õîðîø!" : "Óâû...";
|
||||
resultText.color = isWin ? new Color(1f, 0.84f, 0f) : Color.white;
|
||||
|
||||
if (gameOverStatusImage != null)
|
||||
gameOverStatusImage.GameOverSwitch(isWin);
|
||||
}
|
||||
|
||||
int credits = ComWrapper.GetPlayerCredits(playerId);
|
||||
|
||||
if (continueButton != null) continueButton.gameObject.SetActive(false);
|
||||
if (replayButton != null) replayButton.gameObject.SetActive(false);
|
||||
|
||||
if (isBotGame)
|
||||
{
|
||||
ShowBotGameButtons(isWin, credits);
|
||||
}
|
||||
else
|
||||
{
|
||||
ShowPvPGameButtons(credits);
|
||||
}
|
||||
}
|
||||
|
||||
private void ShowBotGameButtons(bool isWin, int credits)
|
||||
{
|
||||
if (isWin)
|
||||
{
|
||||
if (continueButton != null)
|
||||
{
|
||||
continueButton.gameObject.SetActive(true);
|
||||
continueButton.interactable = true;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (replayButton != null)
|
||||
{
|
||||
replayButton.gameObject.SetActive(true);
|
||||
replayButton.interactable = credits >= 1;
|
||||
var txt = replayButton.GetComponentInChildren<TMP_Text>();
|
||||
if (txt != null) txt.text = "Ïåðåèãðàòü";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void ShowPvPGameButtons(int credits)
|
||||
{
|
||||
if (replayButton != null)
|
||||
{
|
||||
int oponentId = playerId == 1 ? 2 : 1;
|
||||
int oponentCredits = ComWrapper.GetPlayerCredits(oponentId);
|
||||
|
||||
replayButton.gameObject.SetActive(true);
|
||||
replayButton.interactable = credits >= 2 || (credits >= 1 && oponentCredits >= 1);
|
||||
var txt = replayButton.GetComponentInChildren<TMP_Text>();
|
||||
if (txt != null) txt.text = "Åù¸ ðàç!";
|
||||
}
|
||||
}
|
||||
|
||||
public void UpdateButtons()
|
||||
{
|
||||
int credits = ComWrapper.GetPlayerCredits(playerId);
|
||||
int oponentId = playerId == 1 ? 2 : 1;
|
||||
int oponentCredits = ComWrapper.GetPlayerCredits(oponentId);
|
||||
|
||||
if (continueButton != null && continueButton.gameObject.activeSelf)
|
||||
continueButton.interactable = credits >= 1;
|
||||
|
||||
if (replayButton != null && replayButton.gameObject.activeSelf)
|
||||
{
|
||||
if (gameManager != null && gameManager.gameMode == GameMode.PlayerVsBot)
|
||||
replayButton.interactable = credits >= 1;
|
||||
else
|
||||
replayButton.interactable = credits >= 2 || (credits >= 1 && oponentCredits >= 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1,3 +0,0 @@
|
||||
fileFormatVersion: 2
|
||||
guid: da85480a628a444182a5c189091dc623
|
||||
timeCreated: 1770037344
|
||||
@ -1,74 +0,0 @@
|
||||
using UnityEngine;
|
||||
using UnityEngine.UI;
|
||||
|
||||
/// <summary>
|
||||
/// Îòâå÷àåò çà îáíîâëåíèå interactable ñîñòîÿíèÿ êíîïîê ãëàâíîãî ìåíþ ïî áàëàíñó
|
||||
/// </summary>
|
||||
public class MainMenuButtonsUpdater : MonoBehaviour
|
||||
{
|
||||
[SerializeField] private int playerId;
|
||||
[SerializeField] private Button playVsBotButton;
|
||||
[SerializeField] private Button playVsPlayerButton;
|
||||
|
||||
private bool eventsSubscribed;
|
||||
|
||||
private void OnEnable()
|
||||
{
|
||||
ComWrapper.OnInitialize += Subscribe;
|
||||
|
||||
if (!eventsSubscribed && (ComWrapper.onCoinAdded != null || ComWrapper.onCoinRemoved != null))
|
||||
Subscribe();
|
||||
}
|
||||
|
||||
private void OnDisable()
|
||||
{
|
||||
if (eventsSubscribed)
|
||||
{
|
||||
if (ComWrapper.onCoinAdded != null) ComWrapper.onCoinAdded.RemoveListener(OnCoinsChanged);
|
||||
if (ComWrapper.onCoinRemoved != null) ComWrapper.onCoinRemoved.RemoveListener(OnCoinsChanged);
|
||||
eventsSubscribed = false;
|
||||
}
|
||||
|
||||
ComWrapper.OnInitialize -= Subscribe;
|
||||
}
|
||||
|
||||
private void Subscribe()
|
||||
{
|
||||
if (eventsSubscribed) return;
|
||||
|
||||
if (ComWrapper.onCoinAdded != null) ComWrapper.onCoinAdded.AddListener(OnCoinsChanged);
|
||||
if (ComWrapper.onCoinRemoved != null) ComWrapper.onCoinRemoved.AddListener(OnCoinsChanged);
|
||||
|
||||
eventsSubscribed = true;
|
||||
UpdateButtons();
|
||||
}
|
||||
|
||||
private void Start()
|
||||
{
|
||||
UpdateButtons();
|
||||
}
|
||||
|
||||
private void OnCoinsChanged(int playerID, int newAmount)
|
||||
{
|
||||
UpdateButtons();
|
||||
}
|
||||
|
||||
public void UpdateButtons()
|
||||
{
|
||||
int myCoins = ComWrapper.GetPlayerCredits(playerId);
|
||||
int enemyId = playerId == 1 ? 2 : 1;
|
||||
int enemyCoins = ComWrapper.GetPlayerCredits(enemyId);
|
||||
|
||||
bool freePlay = SettingsManager.instance != null &&
|
||||
SettingsManager.instance.GetSettingValue("Áåñïëàòíàÿ èãðà") == "Âêë";
|
||||
|
||||
if (playVsBotButton != null)
|
||||
playVsBotButton.interactable = myCoins >= 1 || freePlay;
|
||||
|
||||
bool bothHaveEnough = myCoins >= 2 || (myCoins >= 1 && enemyCoins >= 1) || freePlay;
|
||||
|
||||
if (playVsPlayerButton != null)
|
||||
playVsPlayerButton.interactable = bothHaveEnough;
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,3 +0,0 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 868ec3b4c73d4bddaffbbec6ed83002a
|
||||
timeCreated: 1770037344
|
||||
@ -1,51 +0,0 @@
|
||||
using UnityEngine;
|
||||
using UnityEngine.UI;
|
||||
|
||||
public class PlacementChoiceOverlay : MonoBehaviour
|
||||
{
|
||||
[SerializeField] private GameManager gameManager;
|
||||
[SerializeField] private UIManager uiManager;
|
||||
[SerializeField] private Button autoButton;
|
||||
[SerializeField] private Button manualButton;
|
||||
|
||||
[Header("Optional focus after auto")]
|
||||
[SerializeField] private Button focusAfterAuto; // êíîïêà "â áîé" íà ýêðàíå ðàññòàíîâêè
|
||||
|
||||
private void Awake()
|
||||
{
|
||||
if (autoButton != null) autoButton.onClick.AddListener(OnAuto);
|
||||
if (manualButton != null) manualButton.onClick.AddListener(OnManual);
|
||||
|
||||
}
|
||||
|
||||
private void OnAuto()
|
||||
{
|
||||
if (gameManager == null || uiManager == null) return;
|
||||
|
||||
uiManager.HideAllOverlays();
|
||||
gameManager.SetState(GameState.ShipPlacement);
|
||||
gameManager.SetInputMode(GameManager.InputMode.UI);
|
||||
|
||||
// Àâòî-ðàññòàíîâêà
|
||||
gameManager.ArrangeGame();
|
||||
|
||||
// Íàâåñòè êóðñîð íà êíîïêó "â áîé"
|
||||
if (focusAfterAuto != null)
|
||||
{
|
||||
var highlight = focusAfterAuto.GetComponent<UIButtonHighlight>();
|
||||
if (highlight != null)
|
||||
highlight.SetHighlighted(true);
|
||||
}
|
||||
}
|
||||
|
||||
private void OnManual()
|
||||
{
|
||||
if (gameManager == null || uiManager == null) return;
|
||||
|
||||
uiManager.HideAllOverlays();
|
||||
gameManager.SetState(GameState.ShipPlacement);
|
||||
gameManager.SetInputMode(GameManager.InputMode.ShipPlacement);
|
||||
gameManager.InitTargetCursor(true);
|
||||
// Íè÷åãî íå ðàññòàâëÿåì — èãðîê äåëàåò ñàì
|
||||
}
|
||||
}
|
||||
@ -1,85 +0,0 @@
|
||||
using System.Collections;
|
||||
using UnityEngine;
|
||||
using UnityEngine.UI;
|
||||
|
||||
/// <summary>
|
||||
/// Êîìïîíåíò äëÿ ïëàâíîãî èçìåíåíèÿ çíà÷åíèÿ Slider.
|
||||
/// Âûçûâàé ìåòîä AnimateTo() íàïðÿìóþ äëÿ àíèìàöèè.
|
||||
/// </summary>
|
||||
[RequireComponent(typeof(Slider))]
|
||||
public class SmoothSlider : MonoBehaviour
|
||||
{
|
||||
[Header("Íàñòðîéêè ïëàâíîñòè")]
|
||||
[Tooltip("Äëèòåëüíîñòü àíèìàöèè â ñåêóíäàõ")]
|
||||
[SerializeField] private float duration = 0.3f;
|
||||
|
||||
[Tooltip("Êðèâàÿ àíèìàöèè (ïî óìîë÷àíèþ - ïëàâíàÿ)")]
|
||||
[SerializeField] private AnimationCurve curve = AnimationCurve.EaseInOut(0, 0, 1, 1);
|
||||
|
||||
private Slider slider;
|
||||
private Coroutine animationCoroutine;
|
||||
private float targetValue;
|
||||
private System.Action<float> pendingCallback;
|
||||
private int animationId; // Óíèêàëüíûé ID äëÿ îòñëåæèâàíèÿ îòìåíåííûõ àíèìàöèé
|
||||
|
||||
private void Awake()
|
||||
{
|
||||
slider = GetComponent<Slider>();
|
||||
targetValue = slider.value;
|
||||
animationId = 0;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Ïëàâíî àíèìèðóåò ñëàéäåð ê íîâîìó çíà÷åíèþ.
|
||||
/// Â êîíöå àíèìàöèè âûçîâåò callback onComplete.
|
||||
/// </summary>
|
||||
public void AnimateTo(float endValue, System.Action<float> onComplete = null)
|
||||
{
|
||||
if (animationCoroutine != null)
|
||||
{
|
||||
StopCoroutine(animationCoroutine);
|
||||
|
||||
// ÂÀÆÍÎ: Ñîõðàíÿåì ÑÒÀÐÎÅ öåëåâîå çíà÷åíèå è callback ÏÅÐÅÄ îáíîâëåíèåì
|
||||
float previousTarget = targetValue;
|
||||
System.Action<float> previousCallback = pendingCallback;
|
||||
|
||||
// Óñòàíàâëèâàåì ôèíàëüíîå çíà÷åíèå ïðåäûäóùåé àíèìàöèè
|
||||
slider.value = previousTarget;
|
||||
|
||||
// Âûçûâàåì callback ñ ïðàâèëüíûì ôèíàëüíûì çíà÷åíèåì
|
||||
previousCallback?.Invoke(previousTarget);
|
||||
}
|
||||
|
||||
// Òåïåðü îáíîâëÿåì íà íîâûå çíà÷åíèÿ
|
||||
targetValue = endValue;
|
||||
pendingCallback = onComplete;
|
||||
animationId++; // Íîâûé ID äëÿ íîâîé àíèìàöèè
|
||||
animationCoroutine = StartCoroutine(AnimateToValue(endValue, onComplete, animationId));
|
||||
}
|
||||
|
||||
private IEnumerator AnimateToValue(float endValue, System.Action<float> onComplete, int myAnimationId)
|
||||
{
|
||||
float startValue = slider.value;
|
||||
float elapsed = 0f;
|
||||
|
||||
while (elapsed < duration)
|
||||
{
|
||||
elapsed += Time.unscaledDeltaTime;
|
||||
float t = Mathf.Clamp01(elapsed / duration);
|
||||
|
||||
slider.value = Mathf.Lerp(startValue, endValue, curve.Evaluate(t));
|
||||
yield return null;
|
||||
}
|
||||
|
||||
// Ôèíàëüíîå çíà÷åíèå - òîëüêî åñëè àíèìàöèÿ íå áûëà îòìåíåíà
|
||||
if (myAnimationId == animationId)
|
||||
{
|
||||
slider.value = endValue;
|
||||
targetValue = endValue;
|
||||
onComplete?.Invoke(endValue);
|
||||
|
||||
animationCoroutine = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,3 +0,0 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 5e80540a01c44b2e9f69fbf8a703cee6
|
||||
timeCreated: 1765969628
|
||||
@ -1,9 +0,0 @@
|
||||
using UnityEngine;
|
||||
|
||||
public enum UIPanelLayer { Screen, Overlay }
|
||||
|
||||
public class UIPanelId : MonoBehaviour
|
||||
{
|
||||
public string id; // íàïðèìåð "PlacementHint"
|
||||
public UIPanelLayer layer; // Screen èëè Overlay
|
||||
}
|
||||
Loading…
x
Reference in New Issue
Block a user