This commit is contained in:
unknown
2026-04-15 20:04:28 +05:00
parent 0837589fa2
commit 057f5d3d1e
6 changed files with 198 additions and 45 deletions

View File

@@ -181,6 +181,19 @@ public class InventoryItemFactory : MonoBehaviour
rb.linearVelocity = velocity.Value + (Vector3.up * (config?.dropForce ?? 2f)); rb.linearVelocity = velocity.Value + (Vector3.up * (config?.dropForce ?? 2f));
} }
// Если у ItemData нет связанной модели — создаём простой визуал (куб)
if (itemData != null && itemData.modelPrefab == null && worldItem != null)
{
var visual = GameObject.CreatePrimitive(PrimitiveType.Cube);
visual.name = "Visual";
visual.transform.SetParent(worldItem.transform, false);
visual.transform.localPosition = Vector3.zero;
visual.transform.localScale = Vector3.one * 0.3f;
// Удаляем лишний коллайдер на визуале
var col = visual.GetComponent<Collider>();
if (col != null) GameObject.Destroy(col);
}
return worldItem; return worldItem;
} }

View File

@@ -1,6 +1,7 @@
using UnityEngine; using UnityEngine;
using System.Collections.Generic; using System.Collections.Generic;
using UnityEngine.Events; using UnityEngine.Events;
using System.IO;
public class InventoryManager : MonoBehaviour public class InventoryManager : MonoBehaviour
{ {
@@ -108,37 +109,22 @@ public class InventoryManager : MonoBehaviour
var eventsGO = new GameObject("InventoryEvents"); var eventsGO = new GameObject("InventoryEvents");
eventsGO.AddComponent<InventoryEvents>(); eventsGO.AddComponent<InventoryEvents>();
} }
// Попробуем загрузить сохранённый инвентарь
LoadFromFile();
// Ensure PlayerInput exists and subscribe to input events
if (PlayerInput.Instance == null)
{
var go = new GameObject("PlayerInput");
go.AddComponent<PlayerInput>();
} }
void Update() PlayerInput.Instance.OnToggleInventory += ToggleInventory;
{ PlayerInput.Instance.OnDropPressed += DropSelectedItem;
// Toggle инвентаря на Tab PlayerInput.Instance.OnHotbarSelect += SelectHotbarSlot;
if (Input.GetKeyDown(KeyCode.Tab))
{
ToggleInventory();
} }
// Закрыть на Escape
if (Input.GetKeyDown(KeyCode.Escape) && inventoryPanel != null && inventoryPanel.activeSelf)
{
ToggleInventory();
}
// Горячие клавиши 1-9 для хотбара
for (int i = 0; i < 9; i++)
{
if (Input.GetKeyDown(KeyCode.Alpha1 + i))
{
SelectHotbarSlot(i);
}
}
// Выброс предмета на Q
if (Input.GetKeyDown(KeyCode.Q))
{
DropSelectedItem();
}
}
public void ToggleInventory() public void ToggleInventory()
{ {
@@ -151,11 +137,15 @@ public class InventoryManager : MonoBehaviour
{ {
Cursor.lockState = CursorLockMode.None; Cursor.lockState = CursorLockMode.None;
InventoryEvents.Instance?.OnInventoryOpened?.Invoke(); InventoryEvents.Instance?.OnInventoryOpened?.Invoke();
if (PlayerInput.Instance != null)
PlayerInput.Instance.Enabled = false;
} }
else else
{ {
Cursor.lockState = CursorLockMode.Locked; Cursor.lockState = CursorLockMode.Locked;
InventoryEvents.Instance?.OnInventoryClosed?.Invoke(); InventoryEvents.Instance?.OnInventoryClosed?.Invoke();
if (PlayerInput.Instance != null)
PlayerInput.Instance.Enabled = true;
} }
} }
} }
@@ -568,6 +558,49 @@ public class InventoryManager : MonoBehaviour
return JsonUtility.ToJson(inventoryData, true); return JsonUtility.ToJson(inventoryData, true);
} }
/// <summary>
/// Сохранить инвентарь в файл (Application.persistentDataPath)
/// </summary>
public void SaveToFile()
{
try
{
string json = ExportToJson();
string path = Path.Combine(Application.persistentDataPath, "inventory_save.json");
File.WriteAllText(path, json);
Debug.Log($"[InventoryManager] Saved inventory to: {path}");
}
catch (System.Exception ex)
{
Debug.LogError($"[InventoryManager] Failed to save inventory: {ex}");
}
}
/// <summary>
/// Загрузить инвентарь из файла (если есть)
/// </summary>
public void LoadFromFile()
{
try
{
string path = Path.Combine(Application.persistentDataPath, "inventory_save.json");
if (File.Exists(path))
{
string json = File.ReadAllText(path);
ImportFromJson(json);
Debug.Log($"[InventoryManager] Loaded inventory from: {path}");
}
else
{
Debug.Log("[InventoryManager] No save file found.");
}
}
catch (System.Exception ex)
{
Debug.LogError($"[InventoryManager] Failed to load inventory: {ex}");
}
}
public void ImportFromJson(string json) public void ImportFromJson(string json)
{ {
var inventoryData = JsonUtility.FromJson<InventorySaveData>(json); var inventoryData = JsonUtility.FromJson<InventorySaveData>(json);
@@ -598,4 +631,9 @@ public class InventoryManager : MonoBehaviour
public string itemId; public string itemId;
public int amount; public int amount;
} }
void OnApplicationQuit()
{
SaveToFile();
}
} }

View File

@@ -90,7 +90,6 @@ public class InventorySceneSetup
// Компонент предмета // Компонент предмета
var worldItem = itemGO.AddComponent<WorldItem>(); var worldItem = itemGO.AddComponent<WorldItem>();
worldItem.pickupDelay = 0f; // мгновенный подбор
worldItem.useFactory = false; worldItem.useFactory = false;
// Тестовые данные // Тестовые данные
@@ -101,8 +100,8 @@ public class InventorySceneSetup
testItem.type = ItemType.Material; testItem.type = ItemType.Material;
testItem.maxStack = 64; testItem.maxStack = 64;
worldItem.itemData = testItem; // Используем Setup чтобы инициализировать визуал и включить мгновенный подбор
worldItem.amount = 5; worldItem.Setup(testItem, 5);
// Коллайдер для подбора (trigger для обычных коллайдеров) // Коллайдер для подбора (trigger для обычных коллайдеров)
var box = itemGO.AddComponent<BoxCollider>(); var box = itemGO.AddComponent<BoxCollider>();
@@ -141,6 +140,15 @@ public class InventorySceneSetup
canvas.sortingOrder = 100; canvas.sortingOrder = 100;
canvasGO.AddComponent<GraphicRaycaster>(); canvasGO.AddComponent<GraphicRaycaster>();
// Ensure EventSystem exists for UI interaction
var existingES = GameObject.FindObjectOfType<UnityEngine.EventSystems.EventSystem>();
if (existingES == null)
{
var es = new GameObject("EventSystem");
es.AddComponent<UnityEngine.EventSystems.EventSystem>();
es.AddComponent<UnityEngine.EventSystems.StandaloneInputModule>();
}
// Создаём панель инвентаря // Создаём панель инвентаря
var inventoryPanel = CreatePanel(canvasGO.transform, "InventoryPanel", new Color(0.15f, 0.15f, 0.15f, 0.95f)); var inventoryPanel = CreatePanel(canvasGO.transform, "InventoryPanel", new Color(0.15f, 0.15f, 0.15f, 0.95f));
var inventoryRect = inventoryPanel.GetComponent<RectTransform>(); var inventoryRect = inventoryPanel.GetComponent<RectTransform>();

View File

@@ -0,0 +1,79 @@
using UnityEngine;
using System;
public class PlayerInput : MonoBehaviour
{
public static PlayerInput Instance { get; private set; }
// Continuous axes
public float MouseX { get; private set; }
public float MouseY { get; private set; }
public float Horizontal { get; private set; }
public float Vertical { get; private set; }
// Continuous states
public bool Crouch { get; private set; }
public bool Run { get; private set; }
// Events for discrete actions
public event Action OnToggleInventory;
public event Action OnDropPressed;
public event Action OnPickupPressed;
public event Action OnJumpPressed;
public event Action<int> OnHotbarSelect;
public bool Enabled { get; set; } = true;
void Awake()
{
if (Instance == null)
{
Instance = this;
DontDestroyOnLoad(gameObject);
}
else
{
Destroy(gameObject);
}
}
void Update()
{
// Always allow toggle inventory (Tab/Escape) even when input is disabled
if (Input.GetKeyDown(KeyCode.Tab) || Input.GetKeyDown(KeyCode.Escape))
OnToggleInventory?.Invoke();
if (!Enabled) return;
// Axes
MouseX = Input.GetAxis("Mouse X");
MouseY = Input.GetAxis("Mouse Y");
Horizontal = Input.GetAxisRaw("Horizontal");
Vertical = Input.GetAxisRaw("Vertical");
// Continuous keys
Crouch = Input.GetKey(KeyCode.C);
Run = Input.GetKey(KeyCode.LeftShift);
// Discrete actions
if (Input.GetButtonDown("Jump"))
OnJumpPressed?.Invoke();
if (Input.GetKeyDown(KeyCode.Tab))
OnToggleInventory?.Invoke();
if (Input.GetKeyDown(KeyCode.Q))
OnDropPressed?.Invoke();
if (Input.GetKeyDown(KeyCode.E))
OnPickupPressed?.Invoke();
for (int i = 0; i < 9; i++)
{
if (Input.GetKeyDown(KeyCode.Alpha1 + i))
{
OnHotbarSelect?.Invoke(i);
}
}
}
}

View File

@@ -0,0 +1,2 @@
fileFormatVersion: 2
guid: cb5fd82e043d6694e90df66d2b3f267a

View File

@@ -31,6 +31,7 @@ public class charecter : MonoBehaviour
float _headYaw; float _headYaw;
float _pitch; float _pitch;
Quaternion _headBindPose; Quaternion _headBindPose;
bool _jumpRequested = false;
// Animator parameter hashes — no hardcoded strings at runtime // Animator parameter hashes — no hardcoded strings at runtime
static readonly int HashSpeed = Animator.StringToHash("Speed"); static readonly int HashSpeed = Animator.StringToHash("Speed");
@@ -49,22 +50,28 @@ public class charecter : MonoBehaviour
_bodyYaw = transform.eulerAngles.y; _bodyYaw = transform.eulerAngles.y;
_headYaw = _bodyYaw; _headYaw = _bodyYaw;
_headBindPose = head.localRotation; _headBindPose = head.localRotation;
// Ensure PlayerInput exists and subscribe to events
if (PlayerInput.Instance == null)
{
var go = new GameObject("PlayerInput");
go.AddComponent<PlayerInput>();
}
PlayerInput.Instance.OnPickupPressed += () => TryPickupNearbyItem();
PlayerInput.Instance.OnJumpPressed += () => { _jumpRequested = true; };
} }
void Update() void Update()
{ {
HandleLook(); HandleLook();
HandleMovement(); HandleMovement();
HandlePickup();
} }
// ── Item Pickup ─────────────────────────────────────────────────────────── // ── Item Pickup ───────────────────────────────────────────────────────────
void HandlePickup() void HandlePickup()
{ {
if (Input.GetKeyDown(KeyCode.E)) // Input moved to PlayerInput events
{
TryPickupNearbyItem();
}
} }
void TryPickupNearbyItem() void TryPickupNearbyItem()
@@ -115,19 +122,24 @@ public class charecter : MonoBehaviour
// ── Mouse look ──────────────────────────────────────────────────────────── // ── Mouse look ────────────────────────────────────────────────────────────
void HandleLook() void HandleLook()
{ {
_headYaw += Input.GetAxis("Mouse X") * mouseSensitivity; var input = PlayerInput.Instance;
_pitch -= Input.GetAxis("Mouse Y") * mouseSensitivity; if (input != null)
{
_headYaw += input.MouseX * mouseSensitivity;
_pitch -= input.MouseY * mouseSensitivity;
}
_pitch = Mathf.Clamp(_pitch, -maxPitch, maxPitch); _pitch = Mathf.Clamp(_pitch, -maxPitch, maxPitch);
} }
// ── Movement ────────────────────────────────────────────────────────────── // ── Movement ──────────────────────────────────────────────────────────────
void HandleMovement() void HandleMovement()
{ {
float h = Input.GetAxisRaw("Horizontal"); var input = PlayerInput.Instance;
float v = Input.GetAxisRaw("Vertical"); float h = input != null ? input.Horizontal : Input.GetAxisRaw("Horizontal");
float v = input != null ? input.Vertical : Input.GetAxisRaw("Vertical");
bool isCrouching = Input.GetKey(KeyCode.C); bool isCrouching = input != null ? input.Crouch : Input.GetKey(KeyCode.C);
bool isRunning = Input.GetKey(KeyCode.LeftShift) && !isCrouching; bool isRunning = input != null ? input.Run && !isCrouching : Input.GetKey(KeyCode.LeftShift) && !isCrouching;
bool isMoving = (h * h + v * v) > 0.01f; bool isMoving = (h * h + v * v) > 0.01f;
float speed = isCrouching ? crouchSpeed : isRunning ? runSpeed : walkSpeed; float speed = isCrouching ? crouchSpeed : isRunning ? runSpeed : walkSpeed;
@@ -147,11 +159,12 @@ public class charecter : MonoBehaviour
{ {
if (_verticalVelocity < 0f) _verticalVelocity = -2f; if (_verticalVelocity < 0f) _verticalVelocity = -2f;
if (Input.GetButtonDown("Jump") && !isCrouching) if (_jumpRequested && !isCrouching)
{ {
_verticalVelocity = Mathf.Sqrt(jumpHeight * -2f * gravity); _verticalVelocity = Mathf.Sqrt(jumpHeight * -2f * gravity);
_anim?.SetTrigger(HashJump); _anim?.SetTrigger(HashJump);
} }
_jumpRequested = false;
} }
_verticalVelocity += gravity * Time.deltaTime; _verticalVelocity += gravity * Time.deltaTime;