first commit

This commit is contained in:
2026-06-04 21:37:43 +03:00
commit a6ea987b0d
152 changed files with 34059 additions and 0 deletions
+65
View File
@@ -0,0 +1,65 @@
using UnityEngine;
namespace OTG.Lab06.Characters
{
public sealed class ManaCrystal : MonoBehaviour
{
[SerializeField] private float restoreAmount = 35f;
[SerializeField] private float respawnTime = 7f;
[SerializeField] private GameObject visualRoot;
private Collider triggerCollider;
private float cooldown;
private void Awake()
{
triggerCollider = GetComponent<Collider>();
if (visualRoot == null && transform.childCount > 0)
{
visualRoot = transform.GetChild(0).gameObject;
}
}
private void Update()
{
transform.Rotate(Vector3.up, 45f * Time.deltaTime, Space.World);
if (cooldown <= 0f)
{
return;
}
cooldown -= Time.deltaTime;
if (cooldown <= 0f)
{
SetAvailable(true);
}
}
private void OnTriggerEnter(Collider other)
{
PlayerStats stats = other.GetComponentInParent<PlayerStats>();
if (stats == null || cooldown > 0f)
{
return;
}
stats.RestoreMana(restoreAmount);
cooldown = respawnTime;
SetAvailable(false);
}
private void SetAvailable(bool available)
{
if (triggerCollider != null)
{
triggerCollider.enabled = available;
}
if (visualRoot != null)
{
visualRoot.SetActive(available);
}
}
}
}
@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: cf05fce7fd259f2ef9cfdd279ef00cc0
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
@@ -0,0 +1,58 @@
using UnityEngine;
namespace OTG.Lab06.Characters
{
[RequireComponent(typeof(CharacterController))]
public sealed class PlayerController : MonoBehaviour
{
[SerializeField] private float moveSpeed = 6f;
[SerializeField] private float rotationSpeed = 12f;
[SerializeField] private float gravity = -24f;
[SerializeField] private Transform cameraTransform;
private CharacterController characterController;
private float verticalVelocity;
private void Awake()
{
characterController = GetComponent<CharacterController>();
}
private void Start()
{
if (cameraTransform == null && Camera.main != null)
{
cameraTransform = Camera.main.transform;
}
}
private void Update()
{
Vector2 input = new Vector2(Input.GetAxisRaw("Horizontal"), Input.GetAxisRaw("Vertical"));
input = Vector2.ClampMagnitude(input, 1f);
Vector3 forward = cameraTransform == null ? Vector3.forward : cameraTransform.forward;
Vector3 right = cameraTransform == null ? Vector3.right : cameraTransform.right;
forward.y = 0f;
right.y = 0f;
forward.Normalize();
right.Normalize();
Vector3 move = forward * input.y + right * input.x;
if (move.sqrMagnitude > 0.01f)
{
Quaternion targetRotation = Quaternion.LookRotation(move, Vector3.up);
transform.rotation = Quaternion.Slerp(transform.rotation, targetRotation, rotationSpeed * Time.deltaTime);
}
if (characterController.isGrounded && verticalVelocity < 0f)
{
verticalVelocity = -2f;
}
verticalVelocity += gravity * Time.deltaTime;
Vector3 velocity = move * moveSpeed + Vector3.up * verticalVelocity;
characterController.Move(velocity * Time.deltaTime);
}
}
}
@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: d36fc8809523bc02b9b0f6db8d4ecd1b
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
+71
View File
@@ -0,0 +1,71 @@
using System;
using OTG.Lab06.Core;
using UnityEngine;
namespace OTG.Lab06.Characters
{
public sealed class PlayerStats : MonoBehaviour
{
[SerializeField] private float health = 100f;
[SerializeField] private float mana = 100f;
private ResourceStat healthStat;
private ResourceStat manaStat;
public event Action<float, float> HealthChanged;
public event Action<float, float> ManaChanged;
public float Health { get { EnsureInitialized(); return healthStat.Current; } }
public float MaxHealth { get { EnsureInitialized(); return healthStat.Max; } }
public float Mana { get { EnsureInitialized(); return manaStat.Current; } }
public float MaxMana { get { EnsureInitialized(); return manaStat.Max; } }
private void Awake()
{
EnsureInitialized();
}
private void Start()
{
HealthChanged?.Invoke(Health, MaxHealth);
ManaChanged?.Invoke(Mana, MaxMana);
}
public void TakeDamage(float amount)
{
EnsureInitialized();
healthStat.Subtract(amount);
}
public void Heal(float amount)
{
EnsureInitialized();
healthStat.Add(amount);
}
public bool SpendMana(float amount)
{
EnsureInitialized();
return manaStat.TrySpend(amount);
}
public void RestoreMana(float amount)
{
EnsureInitialized();
manaStat.Add(amount);
}
private void EnsureInitialized()
{
if (healthStat != null && manaStat != null)
{
return;
}
healthStat = new ResourceStat(health);
manaStat = new ResourceStat(mana);
healthStat.Changed += (current, max) => HealthChanged?.Invoke(current, max);
manaStat.Changed += (current, max) => ManaChanged?.Invoke(current, max);
}
}
}
@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 0c1de8ed2b96ea7af8f9a5268fd46f43
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
@@ -0,0 +1,71 @@
using UnityEngine;
namespace OTG.Lab06.Characters
{
public sealed class ThirdPersonCamera : MonoBehaviour
{
[SerializeField] private Transform target;
[SerializeField] private float mouseSensitivity = 2.5f;
[SerializeField] private float smoothTime = 0.12f;
[SerializeField] private float minPitch = 45f;
[SerializeField] private float maxPitch = 60f;
[SerializeField] private float initialPitch = 52f;
[SerializeField] private float distance = 14f;
[SerializeField] private float lookAhead = 3.5f;
[SerializeField] private float targetHeight = 1.25f;
private Vector3 velocity;
private float yaw;
private float pitch;
public void SetTarget(Transform newTarget)
{
target = newTarget;
}
private void Start()
{
yaw = transform.eulerAngles.y;
pitch = Mathf.Clamp(initialPitch, minPitch, maxPitch);
Cursor.lockState = CursorLockMode.None;
Cursor.visible = true;
}
private void LateUpdate()
{
if (target == null)
{
return;
}
if (Input.GetMouseButtonDown(1))
{
Cursor.lockState = CursorLockMode.Locked;
Cursor.visible = false;
}
else if (Input.GetMouseButtonUp(1))
{
Cursor.lockState = CursorLockMode.None;
Cursor.visible = true;
}
if (Input.GetMouseButton(1))
{
yaw += Input.GetAxis("Mouse X") * mouseSensitivity;
pitch -= Input.GetAxis("Mouse Y") * mouseSensitivity;
pitch = Mathf.Clamp(pitch, minPitch, maxPitch);
}
Vector3 forward = Quaternion.Euler(0f, yaw, 0f) * Vector3.forward;
float pitchRadians = pitch * Mathf.Deg2Rad;
float horizontalDistance = Mathf.Cos(pitchRadians) * distance;
float height = Mathf.Sin(pitchRadians) * distance;
Vector3 desiredPosition = target.position - forward * horizontalDistance + Vector3.up * height;
Vector3 lookTarget = target.position + forward * lookAhead + Vector3.up * targetHeight;
transform.position = Vector3.SmoothDamp(transform.position, desiredPosition, ref velocity, smoothTime);
transform.rotation = Quaternion.LookRotation(lookTarget - transform.position, Vector3.up);
}
}
}
@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 77a9e5c97b39968429ddf7ef8a6d0687
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant: