first commit

This commit is contained in:
2026-06-04 15:09:10 +03:00
commit c94f0cc648
62 changed files with 9224 additions and 0 deletions
+508
View File
@@ -0,0 +1,508 @@
using System.IO;
using UnityEditor;
using UnityEditor.AI;
using UnityEditor.SceneManagement;
using UnityEngine;
using UnityEngine.AI;
using UnityEngine.SceneManagement;
using UnityEngine.UI;
public static class Lab7SceneBuilder
{
private const string ScenePath = "Assets/_Scenes/TerritoryScene.unity";
[MenuItem("Tools/Lab7/Create Full Territory Scene")]
public static void CreateFullTerritoryScene()
{
Time.timeScale = 1f;
CreateFolders();
EnsureTag("Player");
EnsureTag("Enemy");
Material groundMaterial = GetOrCreateMaterial("Assets/_Materials/Ground.mat", new Color(0.25f, 0.34f, 0.25f, 1f), false);
Material wallMaterial = GetOrCreateMaterial("Assets/_Materials/Walls.mat", new Color(0.38f, 0.39f, 0.42f, 1f), false);
Material playerMaterial = GetOrCreateMaterial("Assets/_Materials/PlayerBlue.mat", new Color(0.1f, 0.35f, 1f, 1f), false);
Material enemyMaterial = GetOrCreateMaterial("Assets/_Materials/EnemyRed.mat", new Color(1f, 0.12f, 0.08f, 1f), false);
Material zoneNeutralMaterial = GetOrCreateMaterial("Assets/_Materials/ZoneTransparent.mat", new Color(0.55f, 0.55f, 0.55f, 0.45f), true);
Scene scene = EditorSceneManager.NewScene(NewSceneSetup.EmptyScene, NewSceneMode.Single);
scene.name = "TerritoryScene";
GameObject ground = CreateGround(groundMaterial);
CreateObstacles(wallMaterial);
Camera mainCamera = CreateCamera();
CreateLight();
TerritoryUI territoryUI = CreateMainUI();
ResourceManager resourceManager = CreateResourceManager(territoryUI);
GameManager gameManager = CreateGameManager(territoryUI);
CaptureZone[] zones = new CaptureZone[]
{
CreateCaptureZone("Zone A", new Vector3(-8f, 0.05f, 6f), zoneNeutralMaterial, mainCamera),
CreateCaptureZone("Zone B", new Vector3(7.5f, 0.05f, 4f), zoneNeutralMaterial, mainCamera),
CreateCaptureZone("Zone C", new Vector3(0f, 0.05f, -7.5f), zoneNeutralMaterial, mainCamera)
};
PlayerController player = CreatePlayer(playerMaterial);
EnemyAI enemyOne = CreateEnemy("Enemy 1", new Vector3(10f, 1f, -9f), enemyMaterial);
EnemyAI enemyTwo = CreateEnemy("Enemy 2", new Vector3(-10f, 1f, -9f), enemyMaterial);
enemyOne.zones = zones;
enemyTwo.zones = zones;
gameManager.zones = zones;
territoryUI.UpdateZoneStatus(zones);
territoryUI.SetScore(0, 0);
territoryUI.HideGameOver();
resourceManager.territoryUI = territoryUI;
gameManager.territoryUI = territoryUI;
gameManager.winPanel = territoryUI.winPanel;
gameManager.winText = territoryUI.winText;
BakeNavMeshIfAvailable(ground);
EditorSceneManager.SaveScene(scene, ScenePath);
AssetDatabase.SaveAssets();
AssetDatabase.Refresh();
Selection.activeObject = player.gameObject;
Debug.Log("Lab 7 territory scene created: " + ScenePath);
}
private static void CreateFolders()
{
CreateFolderIfMissing("Assets", "_Scripts");
CreateFolderIfMissing("Assets", "_Scenes");
CreateFolderIfMissing("Assets", "_Materials");
CreateFolderIfMissing("Assets", "_Prefabs");
CreateFolderIfMissing("Assets", "Editor");
}
private static void CreateFolderIfMissing(string parent, string child)
{
string path = parent + "/" + child;
if (!AssetDatabase.IsValidFolder(path))
{
AssetDatabase.CreateFolder(parent, child);
}
}
private static void EnsureTag(string tag)
{
SerializedObject tagManager = new SerializedObject(AssetDatabase.LoadAllAssetsAtPath("ProjectSettings/TagManager.asset")[0]);
SerializedProperty tagsProperty = tagManager.FindProperty("tags");
for (int i = 0; i < tagsProperty.arraySize; i++)
{
SerializedProperty tagProperty = tagsProperty.GetArrayElementAtIndex(i);
if (tagProperty.stringValue == tag)
{
return;
}
}
tagsProperty.InsertArrayElementAtIndex(tagsProperty.arraySize);
tagsProperty.GetArrayElementAtIndex(tagsProperty.arraySize - 1).stringValue = tag;
tagManager.ApplyModifiedProperties();
}
private static Material GetOrCreateMaterial(string path, Color color, bool transparent)
{
Material material = AssetDatabase.LoadAssetAtPath<Material>(path);
if (material == null)
{
material = new Material(Shader.Find("Standard"));
AssetDatabase.CreateAsset(material, path);
}
material.color = color;
if (transparent)
{
ConfigureTransparentMaterial(material);
}
else
{
ConfigureOpaqueMaterial(material);
}
EditorUtility.SetDirty(material);
return material;
}
private static void ConfigureTransparentMaterial(Material material)
{
material.SetFloat("_Mode", 3f);
material.SetInt("_SrcBlend", (int)UnityEngine.Rendering.BlendMode.SrcAlpha);
material.SetInt("_DstBlend", (int)UnityEngine.Rendering.BlendMode.OneMinusSrcAlpha);
material.SetInt("_ZWrite", 0);
material.DisableKeyword("_ALPHATEST_ON");
material.EnableKeyword("_ALPHABLEND_ON");
material.DisableKeyword("_ALPHAPREMULTIPLY_ON");
material.renderQueue = 3000;
}
private static void ConfigureOpaqueMaterial(Material material)
{
material.SetFloat("_Mode", 0f);
material.SetInt("_SrcBlend", (int)UnityEngine.Rendering.BlendMode.One);
material.SetInt("_DstBlend", (int)UnityEngine.Rendering.BlendMode.Zero);
material.SetInt("_ZWrite", 1);
material.DisableKeyword("_ALPHATEST_ON");
material.DisableKeyword("_ALPHABLEND_ON");
material.DisableKeyword("_ALPHAPREMULTIPLY_ON");
material.renderQueue = -1;
}
private static GameObject CreateGround(Material material)
{
GameObject ground = GameObject.CreatePrimitive(PrimitiveType.Plane);
ground.name = "Ground";
ground.transform.position = Vector3.zero;
ground.transform.localScale = new Vector3(3f, 1f, 3f);
ground.GetComponent<Renderer>().sharedMaterial = material;
GameObjectUtility.SetStaticEditorFlags(ground, StaticEditorFlags.NavigationStatic);
return ground;
}
private static void CreateObstacles(Material material)
{
CreateWall("Wall North", new Vector3(0f, 1f, 14f), new Vector3(28f, 2f, 1f), material);
CreateWall("Wall South", new Vector3(0f, 1f, -14f), new Vector3(28f, 2f, 1f), material);
CreateWall("Wall West", new Vector3(-14f, 1f, 0f), new Vector3(1f, 2f, 28f), material);
CreateWall("Wall East", new Vector3(14f, 1f, 0f), new Vector3(1f, 2f, 28f), material);
CreateWall("Center Block", new Vector3(0f, 1f, 0f), new Vector3(4f, 2f, 2f), material);
CreateWall("Left Cover", new Vector3(-6f, 1f, -2f), new Vector3(2f, 2f, 6f), material);
CreateWall("Right Cover", new Vector3(6f, 1f, -1.5f), new Vector3(2f, 2f, 5f), material);
}
private static GameObject CreateWall(string name, Vector3 position, Vector3 scale, Material material)
{
GameObject wall = GameObject.CreatePrimitive(PrimitiveType.Cube);
wall.name = name;
wall.transform.position = position;
wall.transform.localScale = scale;
wall.GetComponent<Renderer>().sharedMaterial = material;
GameObjectUtility.SetStaticEditorFlags(wall, StaticEditorFlags.NavigationStatic);
return wall;
}
private static Camera CreateCamera()
{
GameObject cameraObject = new GameObject("Main Camera");
Camera camera = cameraObject.AddComponent<Camera>();
camera.tag = "MainCamera";
camera.transform.position = new Vector3(0f, 22f, -20f);
camera.transform.rotation = Quaternion.Euler(55f, 0f, 0f);
camera.orthographic = true;
camera.orthographicSize = 16f;
camera.clearFlags = CameraClearFlags.Skybox;
camera.nearClipPlane = 0.3f;
camera.farClipPlane = 100f;
return camera;
}
private static void CreateLight()
{
GameObject lightObject = new GameObject("Directional Light");
Light light = lightObject.AddComponent<Light>();
light.type = LightType.Directional;
light.intensity = 1.1f;
light.transform.rotation = Quaternion.Euler(50f, -30f, 0f);
}
private static TerritoryUI CreateMainUI()
{
Font font = GetBuiltinFont();
GameObject canvasObject = new GameObject("Main UI Canvas");
Canvas canvas = canvasObject.AddComponent<Canvas>();
canvas.renderMode = RenderMode.ScreenSpaceOverlay;
CanvasScaler scaler = canvasObject.AddComponent<CanvasScaler>();
scaler.uiScaleMode = CanvasScaler.ScaleMode.ScaleWithScreenSize;
scaler.referenceResolution = new Vector2(1920f, 1080f);
canvasObject.AddComponent<GraphicRaycaster>();
TerritoryUI territoryUI = canvasObject.AddComponent<TerritoryUI>();
Text title = CreateOverlayText("Title", canvasObject.transform, font, "Лабораторная работа №7 — Контроль территории", 24, TextAnchor.UpperLeft);
SetRect(title.rectTransform, new Vector2(0f, 1f), new Vector2(0f, 1f), new Vector2(18f, -18f), new Vector2(760f, 38f));
Text controls = CreateOverlayText("Controls", canvasObject.transform, font, "WASD — движение\nЗахватите все контрольные точки", 18, TextAnchor.UpperLeft);
SetRect(controls.rectTransform, new Vector2(0f, 1f), new Vector2(0f, 1f), new Vector2(18f, -56f), new Vector2(430f, 62f));
Text playerPoints = CreateOverlayText("Player Points", canvasObject.transform, font, "Player Points: 0", 20, TextAnchor.UpperLeft);
playerPoints.color = new Color(0.25f, 0.55f, 1f);
SetRect(playerPoints.rectTransform, new Vector2(0f, 1f), new Vector2(0f, 1f), new Vector2(18f, -124f), new Vector2(300f, 32f));
Text enemyPoints = CreateOverlayText("Enemy Points", canvasObject.transform, font, "Enemy Points: 0", 20, TextAnchor.UpperLeft);
enemyPoints.color = new Color(1f, 0.32f, 0.25f);
SetRect(enemyPoints.rectTransform, new Vector2(0f, 1f), new Vector2(0f, 1f), new Vector2(18f, -158f), new Vector2(300f, 32f));
Text zoneStatus = CreateOverlayText("Zone Status", canvasObject.transform, font, "Zone A: Neutral, 50%\nZone B: Neutral, 50%\nZone C: Neutral, 50%", 19, TextAnchor.UpperRight);
SetRect(zoneStatus.rectTransform, new Vector2(1f, 1f), new Vector2(1f, 1f), new Vector2(-18f, -18f), new Vector2(360f, 110f));
GameObject winPanel = CreateWinPanel(canvasObject.transform, font, out Text winText);
territoryUI.playerPointsText = playerPoints;
territoryUI.enemyPointsText = enemyPoints;
territoryUI.zoneStatusText = zoneStatus;
territoryUI.winPanel = winPanel;
territoryUI.winText = winText;
return territoryUI;
}
private static GameObject CreateWinPanel(Transform parent, Font font, out Text winText)
{
GameObject panel = new GameObject("Win Panel");
panel.transform.SetParent(parent, false);
Image image = panel.AddComponent<Image>();
image.color = new Color(0f, 0f, 0f, 0.72f);
RectTransform rectTransform = panel.GetComponent<RectTransform>();
SetRect(rectTransform, new Vector2(0.5f, 0.5f), new Vector2(0.5f, 0.5f), Vector2.zero, new Vector2(760f, 180f));
winText = CreateOverlayText("Win Text", panel.transform, font, "", 32, TextAnchor.MiddleCenter);
winText.color = Color.white;
SetRect(winText.rectTransform, new Vector2(0.5f, 0.5f), new Vector2(0.5f, 0.5f), Vector2.zero, new Vector2(720f, 150f));
panel.SetActive(false);
return panel;
}
private static Text CreateOverlayText(string name, Transform parent, Font font, string text, int fontSize, TextAnchor alignment)
{
GameObject textObject = new GameObject(name);
textObject.transform.SetParent(parent, false);
Text uiText = textObject.AddComponent<Text>();
uiText.font = font;
uiText.text = text;
uiText.fontSize = fontSize;
uiText.alignment = alignment;
uiText.color = Color.white;
uiText.horizontalOverflow = HorizontalWrapMode.Wrap;
uiText.verticalOverflow = VerticalWrapMode.Overflow;
return uiText;
}
private static Font GetBuiltinFont()
{
Font font = Resources.GetBuiltinResource<Font>("LegacyRuntime.ttf");
if (font == null)
{
font = Resources.GetBuiltinResource<Font>("Arial.ttf");
}
return font;
}
private static void SetRect(RectTransform rectTransform, Vector2 anchorMin, Vector2 anchorMax, Vector2 anchoredPosition, Vector2 size)
{
rectTransform.anchorMin = anchorMin;
rectTransform.anchorMax = anchorMax;
rectTransform.pivot = anchorMin == anchorMax ? anchorMin : new Vector2(0.5f, 0.5f);
rectTransform.anchoredPosition = anchoredPosition;
rectTransform.sizeDelta = size;
}
private static ResourceManager CreateResourceManager(TerritoryUI territoryUI)
{
GameObject managerObject = new GameObject("ResourceManager");
ResourceManager resourceManager = managerObject.AddComponent<ResourceManager>();
resourceManager.pointsText = territoryUI.playerPointsText;
resourceManager.enemyPointsText = territoryUI.enemyPointsText;
resourceManager.territoryUI = territoryUI;
return resourceManager;
}
private static GameManager CreateGameManager(TerritoryUI territoryUI)
{
GameObject managerObject = new GameObject("GameManager");
GameManager gameManager = managerObject.AddComponent<GameManager>();
gameManager.territoryUI = territoryUI;
gameManager.winPanel = territoryUI.winPanel;
gameManager.winText = territoryUI.winText;
gameManager.scoreLimit = 100;
return gameManager;
}
private static PlayerController CreatePlayer(Material material)
{
GameObject playerObject = GameObject.CreatePrimitive(PrimitiveType.Capsule);
playerObject.name = "Player";
playerObject.tag = "Player";
playerObject.transform.position = new Vector3(0f, 1f, 10f);
playerObject.GetComponent<Renderer>().sharedMaterial = material;
Object.DestroyImmediate(playerObject.GetComponent<CapsuleCollider>());
CharacterController controller = playerObject.AddComponent<CharacterController>();
controller.radius = 0.5f;
controller.height = 2f;
controller.center = Vector3.zero;
PlayerController player = playerObject.AddComponent<PlayerController>();
player.moveSpeed = 6f;
return player;
}
private static EnemyAI CreateEnemy(string name, Vector3 position, Material material)
{
GameObject enemyObject = GameObject.CreatePrimitive(PrimitiveType.Capsule);
enemyObject.name = name;
enemyObject.tag = "Enemy";
enemyObject.transform.position = position;
enemyObject.GetComponent<Renderer>().sharedMaterial = material;
Object.DestroyImmediate(enemyObject.GetComponent<CapsuleCollider>());
CharacterController controller = enemyObject.AddComponent<CharacterController>();
controller.radius = 0.5f;
controller.height = 2f;
controller.center = Vector3.zero;
Rigidbody rigidbody = enemyObject.AddComponent<Rigidbody>();
rigidbody.isKinematic = true;
rigidbody.useGravity = false;
NavMeshAgent agent = enemyObject.AddComponent<NavMeshAgent>();
agent.speed = 3.5f;
agent.angularSpeed = 360f;
agent.acceleration = 12f;
agent.stoppingDistance = 0.7f;
EnemyAI enemyAI = enemyObject.AddComponent<EnemyAI>();
enemyAI.moveSpeed = 3.5f;
enemyAI.retargetInterval = 2f;
enemyAI.randomFactor = 4f;
return enemyAI;
}
private static CaptureZone CreateCaptureZone(string name, Vector3 position, Material sharedZoneMaterial, Camera mainCamera)
{
GameObject zoneObject = new GameObject(name);
zoneObject.transform.position = position;
SphereCollider trigger = zoneObject.AddComponent<SphereCollider>();
trigger.isTrigger = true;
trigger.radius = 3.1f;
CaptureZone zone = zoneObject.AddComponent<CaptureZone>();
zone.zoneName = name;
zone.captureTime = 5f;
zone.pointsPerSecond = 5;
zone.currentOwner = CaptureZone.Owner.Neutral;
zone.captureProgress = 0.5f;
GameObject visual = GameObject.CreatePrimitive(PrimitiveType.Cylinder);
visual.name = "Visual";
visual.transform.SetParent(zoneObject.transform, false);
visual.transform.localPosition = Vector3.zero;
visual.transform.localScale = new Vector3(6f, 0.035f, 6f);
Object.DestroyImmediate(visual.GetComponent<Collider>());
Renderer renderer = visual.GetComponent<Renderer>();
Material runtimeMaterial = new Material(sharedZoneMaterial);
runtimeMaterial.name = name + " Runtime Zone Material";
renderer.sharedMaterial = runtimeMaterial;
zone.zoneRenderer = renderer;
CreateWorldZoneUI(zoneObject.transform, zone, mainCamera);
return zone;
}
private static void CreateWorldZoneUI(Transform parent, CaptureZone zone, Camera mainCamera)
{
Font font = GetBuiltinFont();
GameObject canvasObject = new GameObject("World UI");
canvasObject.transform.SetParent(parent, false);
canvasObject.transform.localPosition = new Vector3(0f, 3f, 0f);
canvasObject.transform.localRotation = Quaternion.identity;
canvasObject.transform.localScale = Vector3.one * 0.025f;
Canvas canvas = canvasObject.AddComponent<Canvas>();
canvas.renderMode = RenderMode.WorldSpace;
canvas.worldCamera = mainCamera;
RectTransform canvasRect = canvas.GetComponent<RectTransform>();
canvasRect.sizeDelta = new Vector2(220f, 80f);
canvasObject.AddComponent<GraphicRaycaster>();
Text label = CreateOverlayText("Label", canvasObject.transform, font, zone.zoneName + ": Neutral", 18, TextAnchor.MiddleCenter);
label.color = Color.white;
SetRect(label.rectTransform, new Vector2(0.5f, 1f), new Vector2(0.5f, 1f), new Vector2(0f, -18f), new Vector2(220f, 34f));
Slider slider = CreateWorldSlider(canvasObject.transform, out Image fillImage);
slider.value = 0.5f;
ZoneUI zoneUI = canvasObject.AddComponent<ZoneUI>();
zoneUI.zone = zone;
zoneUI.progressSlider = slider;
zoneUI.labelText = label;
zoneUI.fillImage = fillImage;
zoneUI.targetCamera = mainCamera;
}
private static Slider CreateWorldSlider(Transform parent, out Image fillImage)
{
GameObject sliderObject = new GameObject("Progress Slider");
sliderObject.transform.SetParent(parent, false);
Slider slider = sliderObject.AddComponent<Slider>();
RectTransform sliderRect = sliderObject.GetComponent<RectTransform>();
SetRect(sliderRect, new Vector2(0.5f, 0f), new Vector2(0.5f, 0f), new Vector2(0f, 20f), new Vector2(190f, 18f));
slider.minValue = 0f;
slider.maxValue = 1f;
slider.interactable = false;
slider.transition = Selectable.Transition.None;
GameObject backgroundObject = new GameObject("Background");
backgroundObject.transform.SetParent(sliderObject.transform, false);
Image background = backgroundObject.AddComponent<Image>();
background.color = new Color(0f, 0f, 0f, 0.75f);
RectTransform backgroundRect = background.GetComponent<RectTransform>();
backgroundRect.anchorMin = Vector2.zero;
backgroundRect.anchorMax = Vector2.one;
backgroundRect.offsetMin = Vector2.zero;
backgroundRect.offsetMax = Vector2.zero;
GameObject fillAreaObject = new GameObject("Fill Area");
fillAreaObject.transform.SetParent(sliderObject.transform, false);
RectTransform fillAreaRect = fillAreaObject.AddComponent<RectTransform>();
fillAreaRect.anchorMin = Vector2.zero;
fillAreaRect.anchorMax = Vector2.one;
fillAreaRect.offsetMin = new Vector2(2f, 2f);
fillAreaRect.offsetMax = new Vector2(-2f, -2f);
GameObject fillObject = new GameObject("Fill");
fillObject.transform.SetParent(fillAreaObject.transform, false);
fillImage = fillObject.AddComponent<Image>();
fillImage.color = new Color(1f, 0.82f, 0.08f, 1f);
RectTransform fillRect = fillImage.GetComponent<RectTransform>();
fillRect.anchorMin = Vector2.zero;
fillRect.anchorMax = Vector2.one;
fillRect.offsetMin = Vector2.zero;
fillRect.offsetMax = Vector2.zero;
slider.fillRect = fillRect;
slider.targetGraphic = fillImage;
return slider;
}
private static void BakeNavMeshIfAvailable(GameObject ground)
{
if (ground == null)
{
return;
}
try
{
UnityEditor.AI.NavMeshBuilder.ClearAllNavMeshes();
UnityEditor.AI.NavMeshBuilder.BuildNavMesh();
}
catch (System.Exception exception)
{
Debug.LogWarning("NavMesh bake was skipped. EnemyAI fallback movement will still work. " + exception.Message);
}
}
}
+11
View File
@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: eb22434d216ca3c32b79d1cc8f4ba469
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant: