first commit
This commit is contained in:
@@ -0,0 +1,313 @@
|
||||
using System;
|
||||
using UnityEngine;
|
||||
|
||||
[RequireComponent(typeof(SphereCollider))]
|
||||
public class CaptureZone : MonoBehaviour
|
||||
{
|
||||
public enum Owner
|
||||
{
|
||||
Neutral,
|
||||
Player,
|
||||
Enemy
|
||||
}
|
||||
|
||||
public enum CaptureState
|
||||
{
|
||||
Neutral,
|
||||
CapturingByPlayer,
|
||||
CapturedByPlayer,
|
||||
CapturingByEnemy,
|
||||
CapturedByEnemy,
|
||||
Contested
|
||||
}
|
||||
|
||||
[Header("Identity")]
|
||||
public string zoneName = "Zone";
|
||||
|
||||
[Header("Capture")]
|
||||
public Owner currentOwner = Owner.Neutral;
|
||||
[Range(0f, 1f)] public float captureProgress = 0.5f;
|
||||
public float captureTime = 5f;
|
||||
public int playersInside;
|
||||
public int enemiesInside;
|
||||
public int pointsPerSecond = 5;
|
||||
|
||||
[Header("Visuals")]
|
||||
public Renderer zoneRenderer;
|
||||
public Color neutralColor = new Color(0.55f, 0.55f, 0.55f, 0.45f);
|
||||
public Color playerColor = new Color(0.1f, 0.35f, 1f, 0.55f);
|
||||
public Color enemyColor = new Color(1f, 0.12f, 0.08f, 0.55f);
|
||||
public Color contestedColor = new Color(1f, 0.82f, 0.05f, 0.65f);
|
||||
|
||||
public event Action<CaptureZone> onCapturedByPlayer;
|
||||
public event Action<CaptureZone> onCapturedByEnemy;
|
||||
|
||||
private Owner lastNotifiedOwner;
|
||||
private Vector3 baseScale;
|
||||
private float pulseTimer;
|
||||
private float scoreTimer;
|
||||
|
||||
private void Awake()
|
||||
{
|
||||
SphereCollider trigger = GetComponent<SphereCollider>();
|
||||
trigger.isTrigger = true;
|
||||
|
||||
lastNotifiedOwner = currentOwner;
|
||||
baseScale = transform.localScale;
|
||||
ApplyOwnerProgress(currentOwner);
|
||||
UpdateVisual();
|
||||
}
|
||||
|
||||
private void Update()
|
||||
{
|
||||
UpdateCaptureProgress();
|
||||
TickScoreIncome();
|
||||
UpdateVisual();
|
||||
UpdateCapturePulse();
|
||||
}
|
||||
|
||||
private void OnTriggerEnter(Collider other)
|
||||
{
|
||||
if (other.CompareTag("Player"))
|
||||
{
|
||||
playersInside++;
|
||||
}
|
||||
else if (other.CompareTag("Enemy"))
|
||||
{
|
||||
enemiesInside++;
|
||||
}
|
||||
}
|
||||
|
||||
private void OnTriggerExit(Collider other)
|
||||
{
|
||||
if (other.CompareTag("Player"))
|
||||
{
|
||||
playersInside = Mathf.Max(0, playersInside - 1);
|
||||
}
|
||||
else if (other.CompareTag("Enemy"))
|
||||
{
|
||||
enemiesInside = Mathf.Max(0, enemiesInside - 1);
|
||||
}
|
||||
}
|
||||
|
||||
public float GetProgress()
|
||||
{
|
||||
return captureProgress;
|
||||
}
|
||||
|
||||
public Owner GetOwner()
|
||||
{
|
||||
return currentOwner;
|
||||
}
|
||||
|
||||
public string GetStateLabel()
|
||||
{
|
||||
switch (GetCaptureState())
|
||||
{
|
||||
case CaptureState.CapturingByPlayer:
|
||||
return "Capturing by Player";
|
||||
case CaptureState.CapturedByPlayer:
|
||||
return "Player";
|
||||
case CaptureState.CapturingByEnemy:
|
||||
return "Capturing by Enemy";
|
||||
case CaptureState.CapturedByEnemy:
|
||||
return "Enemy";
|
||||
case CaptureState.Contested:
|
||||
return "Contested";
|
||||
default:
|
||||
return "Neutral";
|
||||
}
|
||||
}
|
||||
|
||||
public CaptureState GetCaptureState()
|
||||
{
|
||||
bool hasPlayer = playersInside > 0;
|
||||
bool hasEnemy = enemiesInside > 0;
|
||||
|
||||
if (hasPlayer && hasEnemy)
|
||||
{
|
||||
return CaptureState.Contested;
|
||||
}
|
||||
|
||||
if (hasPlayer && currentOwner != Owner.Player)
|
||||
{
|
||||
return CaptureState.CapturingByPlayer;
|
||||
}
|
||||
|
||||
if (hasEnemy && currentOwner != Owner.Enemy)
|
||||
{
|
||||
return CaptureState.CapturingByEnemy;
|
||||
}
|
||||
|
||||
if (currentOwner == Owner.Player)
|
||||
{
|
||||
return CaptureState.CapturedByPlayer;
|
||||
}
|
||||
|
||||
if (currentOwner == Owner.Enemy)
|
||||
{
|
||||
return CaptureState.CapturedByEnemy;
|
||||
}
|
||||
|
||||
return CaptureState.Neutral;
|
||||
}
|
||||
|
||||
public void ForceSetOwner(Owner owner)
|
||||
{
|
||||
SetOwner(owner, true);
|
||||
}
|
||||
|
||||
private void UpdateCaptureProgress()
|
||||
{
|
||||
bool hasPlayer = playersInside > 0;
|
||||
bool hasEnemy = enemiesInside > 0;
|
||||
|
||||
// Спорная зона замораживает прогресс, чтобы игрок видел механику contest.
|
||||
if (hasPlayer == hasEnemy)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
float step = Time.deltaTime / Mathf.Max(0.1f, captureTime);
|
||||
|
||||
if (hasPlayer)
|
||||
{
|
||||
captureProgress = Mathf.MoveTowards(captureProgress, 1f, step);
|
||||
if (Mathf.Approximately(captureProgress, 1f))
|
||||
{
|
||||
SetOwner(Owner.Player, false);
|
||||
}
|
||||
}
|
||||
else if (hasEnemy)
|
||||
{
|
||||
captureProgress = Mathf.MoveTowards(captureProgress, 0f, step);
|
||||
if (Mathf.Approximately(captureProgress, 0f))
|
||||
{
|
||||
SetOwner(Owner.Enemy, false);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void TickScoreIncome()
|
||||
{
|
||||
if (currentOwner == Owner.Neutral || ResourceManager.Instance == null)
|
||||
{
|
||||
scoreTimer = 0f;
|
||||
return;
|
||||
}
|
||||
|
||||
scoreTimer += Time.deltaTime;
|
||||
if (scoreTimer < 1f)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
int ticks = Mathf.FloorToInt(scoreTimer);
|
||||
scoreTimer -= ticks;
|
||||
int amount = pointsPerSecond * ticks;
|
||||
|
||||
if (currentOwner == Owner.Player)
|
||||
{
|
||||
ResourceManager.Instance.AddPlayerPoints(amount);
|
||||
}
|
||||
else if (currentOwner == Owner.Enemy)
|
||||
{
|
||||
ResourceManager.Instance.AddEnemyPoints(amount);
|
||||
}
|
||||
}
|
||||
|
||||
private void SetOwner(Owner owner, bool forceNotify)
|
||||
{
|
||||
if (currentOwner == owner && !forceNotify)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
Owner previousOwner = currentOwner;
|
||||
currentOwner = owner;
|
||||
ApplyOwnerProgress(owner);
|
||||
pulseTimer = 0.25f;
|
||||
|
||||
if (previousOwner == owner && !forceNotify)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (lastNotifiedOwner != currentOwner || forceNotify)
|
||||
{
|
||||
lastNotifiedOwner = currentOwner;
|
||||
|
||||
if (currentOwner == Owner.Player)
|
||||
{
|
||||
onCapturedByPlayer?.Invoke(this);
|
||||
}
|
||||
else if (currentOwner == Owner.Enemy)
|
||||
{
|
||||
onCapturedByEnemy?.Invoke(this);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void ApplyOwnerProgress(Owner owner)
|
||||
{
|
||||
if (owner == Owner.Player)
|
||||
{
|
||||
captureProgress = 1f;
|
||||
}
|
||||
else if (owner == Owner.Enemy)
|
||||
{
|
||||
captureProgress = 0f;
|
||||
}
|
||||
else if (Mathf.Approximately(captureProgress, 0f) || Mathf.Approximately(captureProgress, 1f))
|
||||
{
|
||||
captureProgress = 0.5f;
|
||||
}
|
||||
}
|
||||
|
||||
private void UpdateVisual()
|
||||
{
|
||||
if (zoneRenderer == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
Color color = GetVisualColor();
|
||||
zoneRenderer.material.color = color;
|
||||
}
|
||||
|
||||
private Color GetVisualColor()
|
||||
{
|
||||
CaptureState state = GetCaptureState();
|
||||
if (state == CaptureState.Contested || state == CaptureState.CapturingByPlayer || state == CaptureState.CapturingByEnemy)
|
||||
{
|
||||
float pulse = Mathf.Lerp(0.75f, 1f, Mathf.PingPong(Time.time * 3f, 1f));
|
||||
return contestedColor * pulse;
|
||||
}
|
||||
|
||||
if (currentOwner == Owner.Player)
|
||||
{
|
||||
return playerColor;
|
||||
}
|
||||
|
||||
if (currentOwner == Owner.Enemy)
|
||||
{
|
||||
return enemyColor;
|
||||
}
|
||||
|
||||
return neutralColor;
|
||||
}
|
||||
|
||||
private void UpdateCapturePulse()
|
||||
{
|
||||
if (pulseTimer <= 0f)
|
||||
{
|
||||
transform.localScale = baseScale;
|
||||
return;
|
||||
}
|
||||
|
||||
pulseTimer -= Time.deltaTime;
|
||||
float t = Mathf.Clamp01(pulseTimer / 0.25f);
|
||||
float scale = 1f + Mathf.Sin(t * Mathf.PI) * 0.12f;
|
||||
transform.localScale = baseScale * scale;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: f3db71fa977ba6416b4d4c8af7de96a0
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,164 @@
|
||||
using UnityEngine;
|
||||
using UnityEngine.AI;
|
||||
|
||||
[RequireComponent(typeof(CharacterController))]
|
||||
public class EnemyAI : MonoBehaviour
|
||||
{
|
||||
public CaptureZone[] zones;
|
||||
public float moveSpeed = 3.5f;
|
||||
public float retargetInterval = 2f;
|
||||
public float stoppingDistance = 0.7f;
|
||||
public float randomFactor = 4f;
|
||||
|
||||
private CharacterController characterController;
|
||||
private NavMeshAgent navMeshAgent;
|
||||
private CaptureZone targetZone;
|
||||
private Vector3 targetOffset;
|
||||
private float retargetTimer;
|
||||
private Vector3 verticalVelocity;
|
||||
|
||||
private void Awake()
|
||||
{
|
||||
characterController = GetComponent<CharacterController>();
|
||||
navMeshAgent = GetComponent<NavMeshAgent>();
|
||||
|
||||
if (navMeshAgent != null)
|
||||
{
|
||||
navMeshAgent.speed = moveSpeed;
|
||||
navMeshAgent.stoppingDistance = stoppingDistance;
|
||||
}
|
||||
}
|
||||
|
||||
private void Start()
|
||||
{
|
||||
ChooseTarget();
|
||||
}
|
||||
|
||||
private void Update()
|
||||
{
|
||||
retargetTimer -= Time.deltaTime;
|
||||
|
||||
if (targetZone == null || targetZone.GetOwner() == CaptureZone.Owner.Enemy || retargetTimer <= 0f)
|
||||
{
|
||||
ChooseTarget();
|
||||
}
|
||||
|
||||
MoveToTarget();
|
||||
}
|
||||
|
||||
private void ChooseTarget()
|
||||
{
|
||||
retargetTimer = retargetInterval + Random.Range(0f, 0.75f);
|
||||
targetZone = null;
|
||||
|
||||
CaptureZone bestPlayerZone = FindBestZone(CaptureZone.Owner.Player);
|
||||
if (bestPlayerZone != null)
|
||||
{
|
||||
SetTarget(bestPlayerZone);
|
||||
return;
|
||||
}
|
||||
|
||||
CaptureZone bestNeutralZone = FindBestZone(CaptureZone.Owner.Neutral);
|
||||
if (bestNeutralZone != null)
|
||||
{
|
||||
SetTarget(bestNeutralZone);
|
||||
}
|
||||
}
|
||||
|
||||
private CaptureZone FindBestZone(CaptureZone.Owner owner)
|
||||
{
|
||||
if (zones == null || zones.Length == 0)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
CaptureZone best = null;
|
||||
float bestScore = float.MaxValue;
|
||||
|
||||
for (int i = 0; i < zones.Length; i++)
|
||||
{
|
||||
CaptureZone zone = zones[i];
|
||||
if (zone == null || zone.GetOwner() != owner)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
float distance = Vector3.Distance(transform.position, zone.transform.position);
|
||||
float score = distance + Random.Range(0f, randomFactor);
|
||||
if (score < bestScore)
|
||||
{
|
||||
bestScore = score;
|
||||
best = zone;
|
||||
}
|
||||
}
|
||||
|
||||
return best;
|
||||
}
|
||||
|
||||
private void SetTarget(CaptureZone zone)
|
||||
{
|
||||
targetZone = zone;
|
||||
Vector2 randomCircle = Random.insideUnitCircle * 1.5f;
|
||||
targetOffset = new Vector3(randomCircle.x, 0f, randomCircle.y);
|
||||
|
||||
if (CanUseNavMeshAgent())
|
||||
{
|
||||
navMeshAgent.SetDestination(GetTargetPosition());
|
||||
}
|
||||
}
|
||||
|
||||
private void MoveToTarget()
|
||||
{
|
||||
if (targetZone == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
Vector3 targetPosition = GetTargetPosition();
|
||||
|
||||
if (CanUseNavMeshAgent())
|
||||
{
|
||||
if (!navMeshAgent.hasPath || Vector3.Distance(navMeshAgent.destination, targetPosition) > 0.5f)
|
||||
{
|
||||
navMeshAgent.SetDestination(targetPosition);
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
Vector3 direction = targetPosition - transform.position;
|
||||
direction.y = 0f;
|
||||
|
||||
if (direction.magnitude <= stoppingDistance)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
Vector3 horizontalMove = direction.normalized * moveSpeed;
|
||||
if (characterController.isGrounded && verticalVelocity.y < 0f)
|
||||
{
|
||||
verticalVelocity.y = -1f;
|
||||
}
|
||||
|
||||
verticalVelocity.y += Physics.gravity.y * Time.deltaTime;
|
||||
characterController.Move((horizontalMove + verticalVelocity) * Time.deltaTime);
|
||||
|
||||
if (horizontalMove.sqrMagnitude > 0.001f)
|
||||
{
|
||||
transform.rotation = Quaternion.LookRotation(horizontalMove.normalized, Vector3.up);
|
||||
}
|
||||
}
|
||||
|
||||
private Vector3 GetTargetPosition()
|
||||
{
|
||||
return targetZone.transform.position + targetOffset;
|
||||
}
|
||||
|
||||
private bool CanUseNavMeshAgent()
|
||||
{
|
||||
return navMeshAgent != null &&
|
||||
navMeshAgent.enabled &&
|
||||
navMeshAgent.isActiveAndEnabled &&
|
||||
navMeshAgent.isOnNavMesh;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 84755881e5af5195ea4faf7db39fdb29
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,153 @@
|
||||
using UnityEngine;
|
||||
using UnityEngine.UI;
|
||||
|
||||
public class GameManager : MonoBehaviour
|
||||
{
|
||||
public CaptureZone[] zones;
|
||||
public TerritoryUI territoryUI;
|
||||
public GameObject winPanel;
|
||||
public Text winText;
|
||||
public int scoreLimit = 100;
|
||||
|
||||
private bool gameOver;
|
||||
|
||||
private void Start()
|
||||
{
|
||||
Time.timeScale = 1f;
|
||||
|
||||
if (territoryUI != null)
|
||||
{
|
||||
territoryUI.HideGameOver();
|
||||
}
|
||||
|
||||
SubscribeToZones();
|
||||
}
|
||||
|
||||
private void Update()
|
||||
{
|
||||
if (gameOver)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (territoryUI != null)
|
||||
{
|
||||
territoryUI.UpdateZoneStatus(zones);
|
||||
}
|
||||
|
||||
CheckVictoryConditions();
|
||||
}
|
||||
|
||||
private void SubscribeToZones()
|
||||
{
|
||||
if (zones == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
for (int i = 0; i < zones.Length; i++)
|
||||
{
|
||||
if (zones[i] == null)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
zones[i].onCapturedByPlayer += OnZoneCaptured;
|
||||
zones[i].onCapturedByEnemy += OnZoneCaptured;
|
||||
}
|
||||
}
|
||||
|
||||
private void OnDestroy()
|
||||
{
|
||||
if (zones == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
for (int i = 0; i < zones.Length; i++)
|
||||
{
|
||||
if (zones[i] == null)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
zones[i].onCapturedByPlayer -= OnZoneCaptured;
|
||||
zones[i].onCapturedByEnemy -= OnZoneCaptured;
|
||||
}
|
||||
}
|
||||
|
||||
private void OnZoneCaptured(CaptureZone zone)
|
||||
{
|
||||
CheckVictoryConditions();
|
||||
}
|
||||
|
||||
private void CheckVictoryConditions()
|
||||
{
|
||||
if (zones == null || zones.Length == 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
bool allPlayer = true;
|
||||
bool allEnemy = true;
|
||||
|
||||
for (int i = 0; i < zones.Length; i++)
|
||||
{
|
||||
if (zones[i] == null)
|
||||
{
|
||||
allPlayer = false;
|
||||
allEnemy = false;
|
||||
continue;
|
||||
}
|
||||
|
||||
allPlayer &= zones[i].GetOwner() == CaptureZone.Owner.Player;
|
||||
allEnemy &= zones[i].GetOwner() == CaptureZone.Owner.Enemy;
|
||||
}
|
||||
|
||||
if (allPlayer)
|
||||
{
|
||||
GameOver("Победа игрока: все зоны захвачены!");
|
||||
return;
|
||||
}
|
||||
|
||||
if (allEnemy)
|
||||
{
|
||||
GameOver("Победа врага: все зоны потеряны!");
|
||||
return;
|
||||
}
|
||||
|
||||
if (ResourceManager.Instance != null && ResourceManager.Instance.playerScore >= scoreLimit)
|
||||
{
|
||||
GameOver("Победа игрока: достигнут лимит очков!");
|
||||
}
|
||||
}
|
||||
|
||||
private void GameOver(string message)
|
||||
{
|
||||
if (gameOver)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
gameOver = true;
|
||||
|
||||
if (territoryUI != null)
|
||||
{
|
||||
territoryUI.ShowGameOver(message);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (winPanel != null)
|
||||
{
|
||||
winPanel.SetActive(true);
|
||||
}
|
||||
|
||||
if (winText != null)
|
||||
{
|
||||
winText.text = message;
|
||||
}
|
||||
}
|
||||
|
||||
Time.timeScale = 0f;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 333c0b0a17a11865b8bced65a4497db2
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,43 @@
|
||||
using UnityEngine;
|
||||
|
||||
[RequireComponent(typeof(CharacterController))]
|
||||
public class PlayerController : MonoBehaviour
|
||||
{
|
||||
[Header("Movement")]
|
||||
public float moveSpeed = 6f;
|
||||
public float gravity = -20f;
|
||||
|
||||
private CharacterController characterController;
|
||||
private Vector3 verticalVelocity;
|
||||
|
||||
private void Awake()
|
||||
{
|
||||
characterController = GetComponent<CharacterController>();
|
||||
}
|
||||
|
||||
private void Update()
|
||||
{
|
||||
float horizontal = Input.GetAxisRaw("Horizontal");
|
||||
float vertical = Input.GetAxisRaw("Vertical");
|
||||
|
||||
Vector3 input = new Vector3(horizontal, 0f, vertical);
|
||||
input = Vector3.ClampMagnitude(input, 1f);
|
||||
|
||||
Vector3 move = input * moveSpeed;
|
||||
|
||||
if (characterController.isGrounded && verticalVelocity.y < 0f)
|
||||
{
|
||||
verticalVelocity.y = -1f;
|
||||
}
|
||||
|
||||
verticalVelocity.y += gravity * Time.deltaTime;
|
||||
move += verticalVelocity;
|
||||
|
||||
characterController.Move(move * Time.deltaTime);
|
||||
|
||||
if (input.sqrMagnitude > 0.001f)
|
||||
{
|
||||
transform.rotation = Quaternion.LookRotation(input, Vector3.up);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 853685d0012a45352a9b673f28614946
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,60 @@
|
||||
using UnityEngine;
|
||||
using UnityEngine.UI;
|
||||
|
||||
public class ResourceManager : MonoBehaviour
|
||||
{
|
||||
public static ResourceManager Instance { get; private set; }
|
||||
|
||||
public int playerScore;
|
||||
public int enemyScore;
|
||||
|
||||
public Text pointsText;
|
||||
public Text enemyPointsText;
|
||||
public TerritoryUI territoryUI;
|
||||
|
||||
private void Awake()
|
||||
{
|
||||
if (Instance != null && Instance != this)
|
||||
{
|
||||
Destroy(gameObject);
|
||||
return;
|
||||
}
|
||||
|
||||
Instance = this;
|
||||
}
|
||||
|
||||
private void Start()
|
||||
{
|
||||
UpdateScoreUI();
|
||||
}
|
||||
|
||||
public void AddPlayerPoints(int amount)
|
||||
{
|
||||
playerScore += Mathf.Max(0, amount);
|
||||
UpdateScoreUI();
|
||||
}
|
||||
|
||||
public void AddEnemyPoints(int amount)
|
||||
{
|
||||
enemyScore += Mathf.Max(0, amount);
|
||||
UpdateScoreUI();
|
||||
}
|
||||
|
||||
private void UpdateScoreUI()
|
||||
{
|
||||
if (pointsText != null)
|
||||
{
|
||||
pointsText.text = "Player Points: " + playerScore;
|
||||
}
|
||||
|
||||
if (enemyPointsText != null)
|
||||
{
|
||||
enemyPointsText.text = "Enemy Points: " + enemyScore;
|
||||
}
|
||||
|
||||
if (territoryUI != null)
|
||||
{
|
||||
territoryUI.SetScore(playerScore, enemyScore);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: bebf81aaa988aac5487915a1a02b5bed
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,81 @@
|
||||
using System.Text;
|
||||
using UnityEngine;
|
||||
using UnityEngine.UI;
|
||||
|
||||
public class TerritoryUI : MonoBehaviour
|
||||
{
|
||||
public Text playerPointsText;
|
||||
public Text enemyPointsText;
|
||||
public Text zoneStatusText;
|
||||
public GameObject winPanel;
|
||||
public Text winText;
|
||||
|
||||
private readonly StringBuilder zoneStatusBuilder = new StringBuilder();
|
||||
|
||||
public void UpdateZoneStatus(CaptureZone[] zones)
|
||||
{
|
||||
if (zoneStatusText == null || zones == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
zoneStatusBuilder.Length = 0;
|
||||
for (int i = 0; i < zones.Length; i++)
|
||||
{
|
||||
CaptureZone zone = zones[i];
|
||||
if (zone == null)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
int percent = Mathf.RoundToInt(zone.GetProgress() * 100f);
|
||||
zoneStatusBuilder.Append(zone.zoneName)
|
||||
.Append(": ")
|
||||
.Append(zone.GetOwner())
|
||||
.Append(", ")
|
||||
.Append(percent)
|
||||
.Append('%');
|
||||
|
||||
if (i < zones.Length - 1)
|
||||
{
|
||||
zoneStatusBuilder.AppendLine();
|
||||
}
|
||||
}
|
||||
|
||||
zoneStatusText.text = zoneStatusBuilder.ToString();
|
||||
}
|
||||
|
||||
public void ShowGameOver(string message)
|
||||
{
|
||||
if (winPanel != null)
|
||||
{
|
||||
winPanel.SetActive(true);
|
||||
}
|
||||
|
||||
if (winText != null)
|
||||
{
|
||||
winText.text = message;
|
||||
}
|
||||
}
|
||||
|
||||
public void HideGameOver()
|
||||
{
|
||||
if (winPanel != null)
|
||||
{
|
||||
winPanel.SetActive(false);
|
||||
}
|
||||
}
|
||||
|
||||
public void SetScore(int playerScore, int enemyScore)
|
||||
{
|
||||
if (playerPointsText != null)
|
||||
{
|
||||
playerPointsText.text = "Player Points: " + playerScore;
|
||||
}
|
||||
|
||||
if (enemyPointsText != null)
|
||||
{
|
||||
enemyPointsText.text = "Enemy Points: " + enemyScore;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 49dcf13b53d69fbb9b2208d2160e6de5
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,70 @@
|
||||
using UnityEngine;
|
||||
using UnityEngine.UI;
|
||||
|
||||
public class ZoneUI : MonoBehaviour
|
||||
{
|
||||
public CaptureZone zone;
|
||||
public Slider progressSlider;
|
||||
public Text labelText;
|
||||
public Image fillImage;
|
||||
public Camera targetCamera;
|
||||
|
||||
public Color neutralColor = Color.gray;
|
||||
public Color playerColor = new Color(0.2f, 0.45f, 1f);
|
||||
public Color enemyColor = new Color(1f, 0.2f, 0.15f);
|
||||
public Color contestedColor = new Color(1f, 0.82f, 0.08f);
|
||||
|
||||
private void LateUpdate()
|
||||
{
|
||||
if (zone == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (progressSlider != null)
|
||||
{
|
||||
progressSlider.value = zone.GetProgress();
|
||||
}
|
||||
|
||||
Color color = GetColorForZone();
|
||||
if (fillImage != null)
|
||||
{
|
||||
fillImage.color = color;
|
||||
}
|
||||
|
||||
if (labelText != null)
|
||||
{
|
||||
labelText.text = zone.zoneName + ": " + zone.GetOwner();
|
||||
labelText.color = color;
|
||||
}
|
||||
|
||||
Camera cameraToUse = targetCamera != null ? targetCamera : Camera.main;
|
||||
if (cameraToUse != null)
|
||||
{
|
||||
transform.rotation = Quaternion.LookRotation(transform.position - cameraToUse.transform.position, Vector3.up);
|
||||
}
|
||||
}
|
||||
|
||||
private Color GetColorForZone()
|
||||
{
|
||||
CaptureZone.CaptureState state = zone.GetCaptureState();
|
||||
if (state == CaptureZone.CaptureState.Contested ||
|
||||
state == CaptureZone.CaptureState.CapturingByPlayer ||
|
||||
state == CaptureZone.CaptureState.CapturingByEnemy)
|
||||
{
|
||||
return contestedColor;
|
||||
}
|
||||
|
||||
if (zone.GetOwner() == CaptureZone.Owner.Player)
|
||||
{
|
||||
return playerColor;
|
||||
}
|
||||
|
||||
if (zone.GetOwner() == CaptureZone.Owner.Enemy)
|
||||
{
|
||||
return enemyColor;
|
||||
}
|
||||
|
||||
return neutralColor;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 245f8e31fc2a8036db5d5bf4201e986a
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
Reference in New Issue
Block a user