fix чать инвенторя
This commit is contained in:
@@ -1,8 +1,8 @@
|
|||||||
fileFormatVersion: 2
|
fileFormatVersion: 2
|
||||||
guid: 91470f1965cf83a4a8c49831ec2f7691
|
guid: 037877a8b07e2d84e8a888f939cfbab6
|
||||||
NativeFormatImporter:
|
folderAsset: yes
|
||||||
|
DefaultImporter:
|
||||||
externalObjects: {}
|
externalObjects: {}
|
||||||
mainObjectFileID: 11400000
|
|
||||||
userData:
|
userData:
|
||||||
assetBundleName:
|
assetBundleName:
|
||||||
assetBundleVariant:
|
assetBundleVariant:
|
||||||
428
Assets/Input/PlayerControls.inputactions
Normal file
428
Assets/Input/PlayerControls.inputactions
Normal file
@@ -0,0 +1,428 @@
|
|||||||
|
{
|
||||||
|
"name": "PlayerControls",
|
||||||
|
"maps": [
|
||||||
|
{
|
||||||
|
"name": "Gameplay",
|
||||||
|
"id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
|
||||||
|
"actions": [
|
||||||
|
{
|
||||||
|
"name": "Move",
|
||||||
|
"type": "Value",
|
||||||
|
"id": "10000000-0000-0000-0000-000000000001",
|
||||||
|
"expectedControlType": "Vector2",
|
||||||
|
"processors": "",
|
||||||
|
"interactions": "",
|
||||||
|
"initialStateCheck": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Look",
|
||||||
|
"type": "Value",
|
||||||
|
"id": "10000000-0000-0000-0000-000000000002",
|
||||||
|
"expectedControlType": "Vector2",
|
||||||
|
"processors": "",
|
||||||
|
"interactions": "",
|
||||||
|
"initialStateCheck": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Jump",
|
||||||
|
"type": "Button",
|
||||||
|
"id": "10000000-0000-0000-0000-000000000003",
|
||||||
|
"expectedControlType": "Button",
|
||||||
|
"processors": "",
|
||||||
|
"interactions": ""
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Run",
|
||||||
|
"type": "Button",
|
||||||
|
"id": "10000000-0000-0000-0000-000000000004",
|
||||||
|
"expectedControlType": "Button",
|
||||||
|
"processors": "",
|
||||||
|
"interactions": ""
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Crouch",
|
||||||
|
"type": "Button",
|
||||||
|
"id": "10000000-0000-0000-0000-000000000005",
|
||||||
|
"expectedControlType": "Button",
|
||||||
|
"processors": "",
|
||||||
|
"interactions": ""
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Pickup",
|
||||||
|
"type": "Button",
|
||||||
|
"id": "10000000-0000-0000-0000-000000000006",
|
||||||
|
"expectedControlType": "Button",
|
||||||
|
"processors": "",
|
||||||
|
"interactions": ""
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Drop",
|
||||||
|
"type": "Button",
|
||||||
|
"id": "10000000-0000-0000-0000-000000000007",
|
||||||
|
"expectedControlType": "Button",
|
||||||
|
"processors": "",
|
||||||
|
"interactions": ""
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Hotbar0",
|
||||||
|
"type": "Button",
|
||||||
|
"id": "20000000-0000-0000-0000-000000000001",
|
||||||
|
"expectedControlType": "Button",
|
||||||
|
"processors": "",
|
||||||
|
"interactions": ""
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Hotbar1",
|
||||||
|
"type": "Button",
|
||||||
|
"id": "20000000-0000-0000-0000-000000000002",
|
||||||
|
"expectedControlType": "Button",
|
||||||
|
"processors": "",
|
||||||
|
"interactions": ""
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Hotbar2",
|
||||||
|
"type": "Button",
|
||||||
|
"id": "20000000-0000-0000-0000-000000000003",
|
||||||
|
"expectedControlType": "Button",
|
||||||
|
"processors": "",
|
||||||
|
"interactions": ""
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Hotbar3",
|
||||||
|
"type": "Button",
|
||||||
|
"id": "20000000-0000-0000-0000-000000000004",
|
||||||
|
"expectedControlType": "Button",
|
||||||
|
"processors": "",
|
||||||
|
"interactions": ""
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Hotbar4",
|
||||||
|
"type": "Button",
|
||||||
|
"id": "20000000-0000-0000-0000-000000000005",
|
||||||
|
"expectedControlType": "Button",
|
||||||
|
"processors": "",
|
||||||
|
"interactions": ""
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Hotbar5",
|
||||||
|
"type": "Button",
|
||||||
|
"id": "20000000-0000-0000-0000-000000000006",
|
||||||
|
"expectedControlType": "Button",
|
||||||
|
"processors": "",
|
||||||
|
"interactions": ""
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Hotbar6",
|
||||||
|
"type": "Button",
|
||||||
|
"id": "20000000-0000-0000-0000-000000000007",
|
||||||
|
"expectedControlType": "Button",
|
||||||
|
"processors": "",
|
||||||
|
"interactions": ""
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Hotbar7",
|
||||||
|
"type": "Button",
|
||||||
|
"id": "20000000-0000-0000-0000-000000000008",
|
||||||
|
"expectedControlType": "Button",
|
||||||
|
"processors": "",
|
||||||
|
"interactions": ""
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Hotbar8",
|
||||||
|
"type": "Button",
|
||||||
|
"id": "20000000-0000-0000-0000-000000000009",
|
||||||
|
"expectedControlType": "Button",
|
||||||
|
"processors": "",
|
||||||
|
"interactions": ""
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"bindings": [
|
||||||
|
{
|
||||||
|
"name": "WASD",
|
||||||
|
"id": "30000000-0000-0000-0000-000000000001",
|
||||||
|
"path": "2DVector",
|
||||||
|
"interactions": "",
|
||||||
|
"processors": "",
|
||||||
|
"groups": "",
|
||||||
|
"action": "Move",
|
||||||
|
"isComposite": true,
|
||||||
|
"isPartOfComposite": false
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "up",
|
||||||
|
"id": "30000000-0000-0000-0000-000000000002",
|
||||||
|
"path": "<Keyboard>/w",
|
||||||
|
"interactions": "",
|
||||||
|
"processors": "",
|
||||||
|
"groups": "KeyboardMouse",
|
||||||
|
"action": "Move",
|
||||||
|
"isComposite": false,
|
||||||
|
"isPartOfComposite": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "down",
|
||||||
|
"id": "30000000-0000-0000-0000-000000000003",
|
||||||
|
"path": "<Keyboard>/s",
|
||||||
|
"interactions": "",
|
||||||
|
"processors": "",
|
||||||
|
"groups": "KeyboardMouse",
|
||||||
|
"action": "Move",
|
||||||
|
"isComposite": false,
|
||||||
|
"isPartOfComposite": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "left",
|
||||||
|
"id": "30000000-0000-0000-0000-000000000004",
|
||||||
|
"path": "<Keyboard>/a",
|
||||||
|
"interactions": "",
|
||||||
|
"processors": "",
|
||||||
|
"groups": "KeyboardMouse",
|
||||||
|
"action": "Move",
|
||||||
|
"isComposite": false,
|
||||||
|
"isPartOfComposite": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "right",
|
||||||
|
"id": "30000000-0000-0000-0000-000000000005",
|
||||||
|
"path": "<Keyboard>/d",
|
||||||
|
"interactions": "",
|
||||||
|
"processors": "",
|
||||||
|
"groups": "KeyboardMouse",
|
||||||
|
"action": "Move",
|
||||||
|
"isComposite": false,
|
||||||
|
"isPartOfComposite": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "",
|
||||||
|
"id": "30000000-0000-0000-0000-000000000010",
|
||||||
|
"path": "<Mouse>/delta",
|
||||||
|
"interactions": "",
|
||||||
|
"processors": "",
|
||||||
|
"groups": "KeyboardMouse",
|
||||||
|
"action": "Look",
|
||||||
|
"isComposite": false,
|
||||||
|
"isPartOfComposite": false
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "",
|
||||||
|
"id": "30000000-0000-0000-0000-000000000020",
|
||||||
|
"path": "<Keyboard>/space",
|
||||||
|
"interactions": "",
|
||||||
|
"processors": "",
|
||||||
|
"groups": "KeyboardMouse",
|
||||||
|
"action": "Jump",
|
||||||
|
"isComposite": false,
|
||||||
|
"isPartOfComposite": false
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "",
|
||||||
|
"id": "30000000-0000-0000-0000-000000000021",
|
||||||
|
"path": "<Keyboard>/leftShift",
|
||||||
|
"interactions": "",
|
||||||
|
"processors": "",
|
||||||
|
"groups": "KeyboardMouse",
|
||||||
|
"action": "Run",
|
||||||
|
"isComposite": false,
|
||||||
|
"isPartOfComposite": false
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "",
|
||||||
|
"id": "30000000-0000-0000-0000-000000000022",
|
||||||
|
"path": "<Keyboard>/c",
|
||||||
|
"interactions": "",
|
||||||
|
"processors": "",
|
||||||
|
"groups": "KeyboardMouse",
|
||||||
|
"action": "Crouch",
|
||||||
|
"isComposite": false,
|
||||||
|
"isPartOfComposite": false
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "",
|
||||||
|
"id": "30000000-0000-0000-0000-000000000023",
|
||||||
|
"path": "<Keyboard>/e",
|
||||||
|
"interactions": "",
|
||||||
|
"processors": "",
|
||||||
|
"groups": "KeyboardMouse",
|
||||||
|
"action": "Pickup",
|
||||||
|
"isComposite": false,
|
||||||
|
"isPartOfComposite": false
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "",
|
||||||
|
"id": "30000000-0000-0000-0000-000000000024",
|
||||||
|
"path": "<Keyboard>/q",
|
||||||
|
"interactions": "",
|
||||||
|
"processors": "",
|
||||||
|
"groups": "KeyboardMouse",
|
||||||
|
"action": "Drop",
|
||||||
|
"isComposite": false,
|
||||||
|
"isPartOfComposite": false
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "",
|
||||||
|
"id": "40000000-0000-0000-0000-000000000001",
|
||||||
|
"path": "<Keyboard>/1",
|
||||||
|
"interactions": "",
|
||||||
|
"processors": "",
|
||||||
|
"groups": "KeyboardMouse",
|
||||||
|
"action": "Hotbar0",
|
||||||
|
"isComposite": false,
|
||||||
|
"isPartOfComposite": false
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "",
|
||||||
|
"id": "40000000-0000-0000-0000-000000000002",
|
||||||
|
"path": "<Keyboard>/2",
|
||||||
|
"interactions": "",
|
||||||
|
"processors": "",
|
||||||
|
"groups": "KeyboardMouse",
|
||||||
|
"action": "Hotbar1",
|
||||||
|
"isComposite": false,
|
||||||
|
"isPartOfComposite": false
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "",
|
||||||
|
"id": "40000000-0000-0000-0000-000000000003",
|
||||||
|
"path": "<Keyboard>/3",
|
||||||
|
"interactions": "",
|
||||||
|
"processors": "",
|
||||||
|
"groups": "KeyboardMouse",
|
||||||
|
"action": "Hotbar2",
|
||||||
|
"isComposite": false,
|
||||||
|
"isPartOfComposite": false
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "",
|
||||||
|
"id": "40000000-0000-0000-0000-000000000004",
|
||||||
|
"path": "<Keyboard>/4",
|
||||||
|
"interactions": "",
|
||||||
|
"processors": "",
|
||||||
|
"groups": "KeyboardMouse",
|
||||||
|
"action": "Hotbar3",
|
||||||
|
"isComposite": false,
|
||||||
|
"isPartOfComposite": false
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "",
|
||||||
|
"id": "40000000-0000-0000-0000-000000000005",
|
||||||
|
"path": "<Keyboard>/5",
|
||||||
|
"interactions": "",
|
||||||
|
"processors": "",
|
||||||
|
"groups": "KeyboardMouse",
|
||||||
|
"action": "Hotbar4",
|
||||||
|
"isComposite": false,
|
||||||
|
"isPartOfComposite": false
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "",
|
||||||
|
"id": "40000000-0000-0000-0000-000000000006",
|
||||||
|
"path": "<Keyboard>/6",
|
||||||
|
"interactions": "",
|
||||||
|
"processors": "",
|
||||||
|
"groups": "KeyboardMouse",
|
||||||
|
"action": "Hotbar5",
|
||||||
|
"isComposite": false,
|
||||||
|
"isPartOfComposite": false
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "",
|
||||||
|
"id": "40000000-0000-0000-0000-000000000007",
|
||||||
|
"path": "<Keyboard>/7",
|
||||||
|
"interactions": "",
|
||||||
|
"processors": "",
|
||||||
|
"groups": "KeyboardMouse",
|
||||||
|
"action": "Hotbar6",
|
||||||
|
"isComposite": false,
|
||||||
|
"isPartOfComposite": false
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "",
|
||||||
|
"id": "40000000-0000-0000-0000-000000000008",
|
||||||
|
"path": "<Keyboard>/8",
|
||||||
|
"interactions": "",
|
||||||
|
"processors": "",
|
||||||
|
"groups": "KeyboardMouse",
|
||||||
|
"action": "Hotbar7",
|
||||||
|
"isComposite": false,
|
||||||
|
"isPartOfComposite": false
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "",
|
||||||
|
"id": "40000000-0000-0000-0000-000000000009",
|
||||||
|
"path": "<Keyboard>/9",
|
||||||
|
"interactions": "",
|
||||||
|
"processors": "",
|
||||||
|
"groups": "KeyboardMouse",
|
||||||
|
"action": "Hotbar8",
|
||||||
|
"isComposite": false,
|
||||||
|
"isPartOfComposite": false
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "UI",
|
||||||
|
"id": "b2c3d4e5-f6a7-8901-bcde-f12345678901",
|
||||||
|
"actions": [
|
||||||
|
{
|
||||||
|
"name": "ToggleInventory",
|
||||||
|
"type": "Button",
|
||||||
|
"id": "50000000-0000-0000-0000-000000000001",
|
||||||
|
"expectedControlType": "Button",
|
||||||
|
"processors": "",
|
||||||
|
"interactions": ""
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "CloseInventory",
|
||||||
|
"type": "Button",
|
||||||
|
"id": "50000000-0000-0000-0000-000000000002",
|
||||||
|
"expectedControlType": "Button",
|
||||||
|
"processors": "",
|
||||||
|
"interactions": ""
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"bindings": [
|
||||||
|
{
|
||||||
|
"name": "",
|
||||||
|
"id": "60000000-0000-0000-0000-000000000001",
|
||||||
|
"path": "<Keyboard>/tab",
|
||||||
|
"interactions": "",
|
||||||
|
"processors": "",
|
||||||
|
"groups": "KeyboardMouse",
|
||||||
|
"action": "ToggleInventory",
|
||||||
|
"isComposite": false,
|
||||||
|
"isPartOfComposite": false
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "",
|
||||||
|
"id": "60000000-0000-0000-0000-000000000002",
|
||||||
|
"path": "<Keyboard>/escape",
|
||||||
|
"interactions": "",
|
||||||
|
"processors": "",
|
||||||
|
"groups": "KeyboardMouse",
|
||||||
|
"action": "CloseInventory",
|
||||||
|
"isComposite": false,
|
||||||
|
"isPartOfComposite": false
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"controlSchemes": [
|
||||||
|
{
|
||||||
|
"name": "KeyboardMouse",
|
||||||
|
"restrictToSuppliedDevices": false,
|
||||||
|
"bindingGroup": "KeyboardMouse",
|
||||||
|
"devices": [
|
||||||
|
{
|
||||||
|
"devicePath": "<Keyboard>",
|
||||||
|
"isOptional": false,
|
||||||
|
"isOR": false
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"devicePath": "<Mouse>",
|
||||||
|
"isOptional": false,
|
||||||
|
"isOR": false
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
14
Assets/Input/PlayerControls.inputactions.meta
Normal file
14
Assets/Input/PlayerControls.inputactions.meta
Normal file
@@ -0,0 +1,14 @@
|
|||||||
|
fileFormatVersion: 2
|
||||||
|
guid: 7d782555f7e02f84ca2502d52361f19a
|
||||||
|
ScriptedImporter:
|
||||||
|
internalIDToNameTable: []
|
||||||
|
externalObjects: {}
|
||||||
|
serializedVersion: 2
|
||||||
|
userData:
|
||||||
|
assetBundleName:
|
||||||
|
assetBundleVariant:
|
||||||
|
script: {fileID: 11500000, guid: 8404be70184654265930450def6a9037, type: 3}
|
||||||
|
generateWrapperCode: 0
|
||||||
|
wrapperCodePath:
|
||||||
|
wrapperClassName:
|
||||||
|
wrapperCodeNamespace:
|
||||||
8
Assets/Inventory/ItemPrefab.meta
Normal file
8
Assets/Inventory/ItemPrefab.meta
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
fileFormatVersion: 2
|
||||||
|
guid: ebd3754781a0d3e48a34311a699ad38b
|
||||||
|
folderAsset: yes
|
||||||
|
DefaultImporter:
|
||||||
|
externalObjects: {}
|
||||||
|
userData:
|
||||||
|
assetBundleName:
|
||||||
|
assetBundleVariant:
|
||||||
135
Assets/Inventory/ItemPrefab/NewItem.prefab
Normal file
135
Assets/Inventory/ItemPrefab/NewItem.prefab
Normal file
@@ -0,0 +1,135 @@
|
|||||||
|
%YAML 1.1
|
||||||
|
%TAG !u! tag:unity3d.com,2011:
|
||||||
|
--- !u!1 &4546282257700047937
|
||||||
|
GameObject:
|
||||||
|
m_ObjectHideFlags: 0
|
||||||
|
m_CorrespondingSourceObject: {fileID: 0}
|
||||||
|
m_PrefabInstance: {fileID: 0}
|
||||||
|
m_PrefabAsset: {fileID: 0}
|
||||||
|
serializedVersion: 6
|
||||||
|
m_Component:
|
||||||
|
- component: {fileID: 1948853633481286021}
|
||||||
|
- component: {fileID: 6658874805278007762}
|
||||||
|
- component: {fileID: 3056228376157587138}
|
||||||
|
m_Layer: 0
|
||||||
|
m_Name: NewItem
|
||||||
|
m_TagString: Untagged
|
||||||
|
m_Icon: {fileID: 0}
|
||||||
|
m_NavMeshLayer: 0
|
||||||
|
m_StaticEditorFlags: 0
|
||||||
|
m_IsActive: 1
|
||||||
|
--- !u!4 &1948853633481286021
|
||||||
|
Transform:
|
||||||
|
m_ObjectHideFlags: 0
|
||||||
|
m_CorrespondingSourceObject: {fileID: 0}
|
||||||
|
m_PrefabInstance: {fileID: 0}
|
||||||
|
m_PrefabAsset: {fileID: 0}
|
||||||
|
m_GameObject: {fileID: 4546282257700047937}
|
||||||
|
serializedVersion: 2
|
||||||
|
m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
|
||||||
|
m_LocalPosition: {x: 0, y: 0, z: 0}
|
||||||
|
m_LocalScale: {x: 1, y: 1, z: 1}
|
||||||
|
m_ConstrainProportionsScale: 0
|
||||||
|
m_Children:
|
||||||
|
- {fileID: 7434756968248499828}
|
||||||
|
m_Father: {fileID: 0}
|
||||||
|
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
|
||||||
|
--- !u!114 &6658874805278007762
|
||||||
|
MonoBehaviour:
|
||||||
|
m_ObjectHideFlags: 0
|
||||||
|
m_CorrespondingSourceObject: {fileID: 0}
|
||||||
|
m_PrefabInstance: {fileID: 0}
|
||||||
|
m_PrefabAsset: {fileID: 0}
|
||||||
|
m_GameObject: {fileID: 4546282257700047937}
|
||||||
|
m_Enabled: 1
|
||||||
|
m_EditorHideFlags: 0
|
||||||
|
m_Script: {fileID: 11500000, guid: b8ac54fbf9ed99e45a83319443952a91, type: 3}
|
||||||
|
m_Name:
|
||||||
|
m_EditorClassIdentifier: Assembly-CSharp::WorldItem
|
||||||
|
itemData: {fileID: 0}
|
||||||
|
amount: 1
|
||||||
|
pickupDelay: 0
|
||||||
|
interactRange: 2.5
|
||||||
|
--- !u!135 &3056228376157587138
|
||||||
|
SphereCollider:
|
||||||
|
m_ObjectHideFlags: 0
|
||||||
|
m_CorrespondingSourceObject: {fileID: 0}
|
||||||
|
m_PrefabInstance: {fileID: 0}
|
||||||
|
m_PrefabAsset: {fileID: 0}
|
||||||
|
m_GameObject: {fileID: 4546282257700047937}
|
||||||
|
m_Material: {fileID: 0}
|
||||||
|
m_IncludeLayers:
|
||||||
|
serializedVersion: 2
|
||||||
|
m_Bits: 0
|
||||||
|
m_ExcludeLayers:
|
||||||
|
serializedVersion: 2
|
||||||
|
m_Bits: 0
|
||||||
|
m_LayerOverridePriority: 0
|
||||||
|
m_IsTrigger: 1
|
||||||
|
m_ProvidesContacts: 0
|
||||||
|
m_Enabled: 1
|
||||||
|
serializedVersion: 3
|
||||||
|
m_Radius: 0.5
|
||||||
|
m_Center: {x: 0, y: 0, z: 0}
|
||||||
|
--- !u!1001 &1495056769490629797
|
||||||
|
PrefabInstance:
|
||||||
|
m_ObjectHideFlags: 0
|
||||||
|
serializedVersion: 2
|
||||||
|
m_Modification:
|
||||||
|
serializedVersion: 3
|
||||||
|
m_TransformParent: {fileID: 1948853633481286021}
|
||||||
|
m_Modifications:
|
||||||
|
- target: {fileID: 282714382156279063, guid: 4fcbba5b8725e254f98c052c4db89e02, type: 3}
|
||||||
|
propertyPath: m_Name
|
||||||
|
value: Visual
|
||||||
|
objectReference: {fileID: 0}
|
||||||
|
- target: {fileID: 8327738622413892305, guid: 4fcbba5b8725e254f98c052c4db89e02, type: 3}
|
||||||
|
propertyPath: m_LocalPosition.x
|
||||||
|
value: 0
|
||||||
|
objectReference: {fileID: 0}
|
||||||
|
- target: {fileID: 8327738622413892305, guid: 4fcbba5b8725e254f98c052c4db89e02, type: 3}
|
||||||
|
propertyPath: m_LocalPosition.y
|
||||||
|
value: 0
|
||||||
|
objectReference: {fileID: 0}
|
||||||
|
- target: {fileID: 8327738622413892305, guid: 4fcbba5b8725e254f98c052c4db89e02, type: 3}
|
||||||
|
propertyPath: m_LocalPosition.z
|
||||||
|
value: 0
|
||||||
|
objectReference: {fileID: 0}
|
||||||
|
- target: {fileID: 8327738622413892305, guid: 4fcbba5b8725e254f98c052c4db89e02, type: 3}
|
||||||
|
propertyPath: m_LocalRotation.w
|
||||||
|
value: 1
|
||||||
|
objectReference: {fileID: 0}
|
||||||
|
- target: {fileID: 8327738622413892305, guid: 4fcbba5b8725e254f98c052c4db89e02, type: 3}
|
||||||
|
propertyPath: m_LocalRotation.x
|
||||||
|
value: 0
|
||||||
|
objectReference: {fileID: 0}
|
||||||
|
- target: {fileID: 8327738622413892305, guid: 4fcbba5b8725e254f98c052c4db89e02, type: 3}
|
||||||
|
propertyPath: m_LocalRotation.y
|
||||||
|
value: 0
|
||||||
|
objectReference: {fileID: 0}
|
||||||
|
- target: {fileID: 8327738622413892305, guid: 4fcbba5b8725e254f98c052c4db89e02, type: 3}
|
||||||
|
propertyPath: m_LocalRotation.z
|
||||||
|
value: 0
|
||||||
|
objectReference: {fileID: 0}
|
||||||
|
- target: {fileID: 8327738622413892305, guid: 4fcbba5b8725e254f98c052c4db89e02, type: 3}
|
||||||
|
propertyPath: m_LocalEulerAnglesHint.x
|
||||||
|
value: 0
|
||||||
|
objectReference: {fileID: 0}
|
||||||
|
- target: {fileID: 8327738622413892305, guid: 4fcbba5b8725e254f98c052c4db89e02, type: 3}
|
||||||
|
propertyPath: m_LocalEulerAnglesHint.y
|
||||||
|
value: 0
|
||||||
|
objectReference: {fileID: 0}
|
||||||
|
- target: {fileID: 8327738622413892305, guid: 4fcbba5b8725e254f98c052c4db89e02, type: 3}
|
||||||
|
propertyPath: m_LocalEulerAnglesHint.z
|
||||||
|
value: 0
|
||||||
|
objectReference: {fileID: 0}
|
||||||
|
m_RemovedComponents: []
|
||||||
|
m_RemovedGameObjects: []
|
||||||
|
m_AddedGameObjects: []
|
||||||
|
m_AddedComponents: []
|
||||||
|
m_SourcePrefab: {fileID: 100100000, guid: 4fcbba5b8725e254f98c052c4db89e02, type: 3}
|
||||||
|
--- !u!4 &7434756968248499828 stripped
|
||||||
|
Transform:
|
||||||
|
m_CorrespondingSourceObject: {fileID: 8327738622413892305, guid: 4fcbba5b8725e254f98c052c4db89e02, type: 3}
|
||||||
|
m_PrefabInstance: {fileID: 1495056769490629797}
|
||||||
|
m_PrefabAsset: {fileID: 0}
|
||||||
@@ -1,5 +1,5 @@
|
|||||||
fileFormatVersion: 2
|
fileFormatVersion: 2
|
||||||
guid: 223ec2dc359ac0845957ab0b29284414
|
guid: 9f444e9048146434087c3db3550617f9
|
||||||
PrefabImporter:
|
PrefabImporter:
|
||||||
externalObjects: {}
|
externalObjects: {}
|
||||||
userData:
|
userData:
|
||||||
@@ -12,9 +12,9 @@ MonoBehaviour:
|
|||||||
m_Script: {fileID: 11500000, guid: 5741b63764436354ebad192c9b71f06c, type: 3}
|
m_Script: {fileID: 11500000, guid: 5741b63764436354ebad192c9b71f06c, type: 3}
|
||||||
m_Name: NewItem
|
m_Name: NewItem
|
||||||
m_EditorClassIdentifier: Assembly-CSharp::ItemData
|
m_EditorClassIdentifier: Assembly-CSharp::ItemData
|
||||||
id: 2
|
id: d28a3db9-17bd-489d-9caf-739005a7c780
|
||||||
itemName: NewItem
|
itemName: NewItem
|
||||||
description: 23
|
description: 123
|
||||||
type: 5
|
type: 5
|
||||||
modelPrefab: {fileID: 282714382156279063, guid: 4fcbba5b8725e254f98c052c4db89e02, type: 3}
|
modelPrefab: {fileID: 282714382156279063, guid: 4fcbba5b8725e254f98c052c4db89e02, type: 3}
|
||||||
icon: {fileID: 21300000, guid: 0115b2d990086ae4cbc31baf7c64e680, type: 3}
|
icon: {fileID: 21300000, guid: 0115b2d990086ae4cbc31baf7c64e680, type: 3}
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
fileFormatVersion: 2
|
fileFormatVersion: 2
|
||||||
guid: e9765c2fbc4980049940f96e9b0f70dc
|
guid: 20cff4d8f616b1140b2264c6f049ba8a
|
||||||
NativeFormatImporter:
|
NativeFormatImporter:
|
||||||
externalObjects: {}
|
externalObjects: {}
|
||||||
mainObjectFileID: 11400000
|
mainObjectFileID: 11400000
|
||||||
|
|||||||
@@ -1,31 +0,0 @@
|
|||||||
%YAML 1.1
|
|
||||||
%TAG !u! tag:unity3d.com,2011:
|
|
||||||
--- !u!114 &11400000
|
|
||||||
MonoBehaviour:
|
|
||||||
m_ObjectHideFlags: 0
|
|
||||||
m_CorrespondingSourceObject: {fileID: 0}
|
|
||||||
m_PrefabInstance: {fileID: 0}
|
|
||||||
m_PrefabAsset: {fileID: 0}
|
|
||||||
m_GameObject: {fileID: 0}
|
|
||||||
m_Enabled: 1
|
|
||||||
m_EditorHideFlags: 0
|
|
||||||
m_Script: {fileID: 11500000, guid: 5741b63764436354ebad192c9b71f06c, type: 3}
|
|
||||||
m_Name: test
|
|
||||||
m_EditorClassIdentifier: Assembly-CSharp::ItemData
|
|
||||||
id: 1
|
|
||||||
itemName: test
|
|
||||||
description: 123
|
|
||||||
type: 0
|
|
||||||
modelPrefab: {fileID: 282714382156279063, guid: 4fcbba5b8725e254f98c052c4db89e02, type: 3}
|
|
||||||
icon: {fileID: 21300000, guid: 0115b2d990086ae4cbc31baf7c64e680, type: 3}
|
|
||||||
maxStack: 64
|
|
||||||
isCraftable: 0
|
|
||||||
craftingRecipe:
|
|
||||||
ingredients: []
|
|
||||||
amounts:
|
|
||||||
resultId:
|
|
||||||
resultAmount: 1
|
|
||||||
weight: 1
|
|
||||||
value: 1
|
|
||||||
isDroppable: 1
|
|
||||||
isStackable: 1
|
|
||||||
@@ -78,52 +78,34 @@ public class InventoryManager : MonoBehaviour
|
|||||||
|
|
||||||
void Start()
|
void Start()
|
||||||
{
|
{
|
||||||
// Инициализация слотов
|
// Слоты созданы editor-инструментом и назначены в Inspector
|
||||||
if (slots == null || slots.Length == 0)
|
if (slots == null || slots.Length == 0)
|
||||||
{
|
Debug.LogWarning("[InventoryManager] Slots not assigned! Run Tools > Setup Complete Scene first.");
|
||||||
Debug.LogWarning("Slots not assigned! Assign them in Inspector or use InventoryUIBuilder.");
|
|
||||||
}
|
|
||||||
else
|
else
|
||||||
{
|
foreach (var slot in slots) slot?.UpdateSlotUI();
|
||||||
foreach (var slot in slots)
|
|
||||||
{
|
|
||||||
slot?.UpdateSlotUI();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (hotbarSlots != null)
|
if (hotbarSlots != null)
|
||||||
{
|
foreach (var slot in hotbarSlots) slot?.UpdateSlotUI();
|
||||||
foreach (var slot in hotbarSlots)
|
|
||||||
{
|
|
||||||
slot?.UpdateSlotUI();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Скрыть инвентарь по умолчанию
|
// Скрыть инвентарь по умолчанию
|
||||||
if (inventoryPanel != null)
|
if (inventoryPanel != null)
|
||||||
inventoryPanel.SetActive(false);
|
inventoryPanel.SetActive(false);
|
||||||
|
|
||||||
// Убедимся что события существуют
|
// Подписка на ввод
|
||||||
if (InventoryEvents.Instance == null)
|
if (PlayerInput.Instance != null)
|
||||||
{
|
{
|
||||||
var eventsGO = new GameObject("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>();
|
|
||||||
}
|
|
||||||
|
|
||||||
PlayerInput.Instance.OnToggleInventory += ToggleInventory;
|
PlayerInput.Instance.OnToggleInventory += ToggleInventory;
|
||||||
PlayerInput.Instance.OnDropPressed += DropSelectedItem;
|
PlayerInput.Instance.OnDropPressed += DropSelectedItem;
|
||||||
PlayerInput.Instance.OnHotbarSelect += SelectHotbarSlot;
|
PlayerInput.Instance.OnHotbarSelect += SelectHotbarSlot;
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Debug.LogWarning("[InventoryManager] PlayerInput not found. Run Tools > Setup Complete Scene first.");
|
||||||
|
}
|
||||||
|
|
||||||
|
// Загрузить сохранённый инвентарь (слоты уже существуют)
|
||||||
|
LoadFromFile();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
public void ToggleInventory()
|
public void ToggleInventory()
|
||||||
@@ -135,14 +117,18 @@ public class InventoryManager : MonoBehaviour
|
|||||||
|
|
||||||
if (!wasActive)
|
if (!wasActive)
|
||||||
{
|
{
|
||||||
|
// Открытие инвентаря
|
||||||
Cursor.lockState = CursorLockMode.None;
|
Cursor.lockState = CursorLockMode.None;
|
||||||
|
Cursor.visible = true;
|
||||||
InventoryEvents.Instance?.OnInventoryOpened?.Invoke();
|
InventoryEvents.Instance?.OnInventoryOpened?.Invoke();
|
||||||
if (PlayerInput.Instance != null)
|
if (PlayerInput.Instance != null)
|
||||||
PlayerInput.Instance.Enabled = false;
|
PlayerInput.Instance.Enabled = false;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
// Закрытие инвентаря
|
||||||
Cursor.lockState = CursorLockMode.Locked;
|
Cursor.lockState = CursorLockMode.Locked;
|
||||||
|
Cursor.visible = false;
|
||||||
InventoryEvents.Instance?.OnInventoryClosed?.Invoke();
|
InventoryEvents.Instance?.OnInventoryClosed?.Invoke();
|
||||||
if (PlayerInput.Instance != null)
|
if (PlayerInput.Instance != null)
|
||||||
PlayerInput.Instance.Enabled = true;
|
PlayerInput.Instance.Enabled = true;
|
||||||
@@ -559,8 +545,10 @@ public class InventoryManager : MonoBehaviour
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Сохранить инвентарь в файл (Application.persistentDataPath)
|
/// Сохранить инвентарь в файл (Application.persistentDataPath).
|
||||||
|
/// Доступно через правый клик на компоненте в Inspector во время Play Mode.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
[ContextMenu("Save Inventory")]
|
||||||
public void SaveToFile()
|
public void SaveToFile()
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
@@ -577,8 +565,11 @@ public class InventoryManager : MonoBehaviour
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Загрузить инвентарь из файла (если есть)
|
/// Загрузить инвентарь из файла (если есть).
|
||||||
|
/// Вызывается из InventoryUIBuilder после создания слотов.
|
||||||
|
/// Доступно через правый клик на компоненте в Inspector во время Play Mode.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
[ContextMenu("Load Inventory")]
|
||||||
public void LoadFromFile()
|
public void LoadFromFile()
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
|
|||||||
@@ -1,12 +1,92 @@
|
|||||||
using UnityEngine;
|
using UnityEngine;
|
||||||
using UnityEditor;
|
using UnityEditor;
|
||||||
using UnityEngine.UI;
|
using UnityEngine.UI;
|
||||||
|
using UnityEngine.EventSystems;
|
||||||
using TMPro;
|
using TMPro;
|
||||||
|
|
||||||
public class InventorySceneSetup
|
/// <summary>
|
||||||
|
/// Tools > Setup Complete Scene — создаёт всё до запуска игры (editor-time).
|
||||||
|
/// Canvas инвентаря помещается внутрь Player.
|
||||||
|
/// InventoryManager получает все ссылки сразу.
|
||||||
|
/// </summary>
|
||||||
|
public static class InventorySceneSetup
|
||||||
{
|
{
|
||||||
[MenuItem("Tools/Create Player")]
|
[MenuItem("Tools/Setup Complete Scene")]
|
||||||
public static void CreatePlayer()
|
public static void SetupCompleteScene()
|
||||||
|
{
|
||||||
|
if (Object.FindObjectOfType<InventoryManager>() != null)
|
||||||
|
{
|
||||||
|
EditorUtility.DisplayDialog(
|
||||||
|
"Сцена уже настроена",
|
||||||
|
"InventoryManager уже существует. Удалите существующие объекты сцены перед повторной настройкой.",
|
||||||
|
"OK");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// ── EventSystem ───────────────────────────────────────────────────────
|
||||||
|
if (Object.FindObjectOfType<EventSystem>() == null)
|
||||||
|
{
|
||||||
|
var esGO = new GameObject("EventSystem");
|
||||||
|
esGO.AddComponent<EventSystem>();
|
||||||
|
esGO.AddComponent<StandaloneInputModule>();
|
||||||
|
}
|
||||||
|
|
||||||
|
// ── InventoryEvents ───────────────────────────────────────────────────
|
||||||
|
new GameObject("InventoryEvents").AddComponent<InventoryEvents>();
|
||||||
|
|
||||||
|
// ── InventoryManager ──────────────────────────────────────────────────
|
||||||
|
var imGO = new GameObject("InventoryManager");
|
||||||
|
var im = imGO.AddComponent<InventoryManager>();
|
||||||
|
imGO.AddComponent<InventoryExampleItems>();
|
||||||
|
|
||||||
|
// ── Player ────────────────────────────────────────────────────────────
|
||||||
|
var player = CreatePlayerGO();
|
||||||
|
|
||||||
|
// ── InventoryCanvas (дочерний объект Player) ──────────────────────────
|
||||||
|
var canvasGO = new GameObject("InventoryCanvas");
|
||||||
|
canvasGO.transform.SetParent(player.transform, false);
|
||||||
|
|
||||||
|
var canvas = canvasGO.AddComponent<Canvas>();
|
||||||
|
canvas.renderMode = RenderMode.ScreenSpaceOverlay;
|
||||||
|
canvas.sortingOrder = 100;
|
||||||
|
canvasGO.AddComponent<GraphicRaycaster>();
|
||||||
|
|
||||||
|
var uiBuilder = canvasGO.AddComponent<InventoryUIBuilder>();
|
||||||
|
|
||||||
|
// Строим весь UI прямо сейчас, до запуска игры
|
||||||
|
uiBuilder.BuildInventoryUI();
|
||||||
|
|
||||||
|
// Назначаем ссылки в InventoryManager
|
||||||
|
im.slots = uiBuilder.GetInventorySlots();
|
||||||
|
im.hotbarSlots = uiBuilder.GetHotbarSlots();
|
||||||
|
im.inventoryPanel = uiBuilder.inventoryPanelRect != null ? uiBuilder.inventoryPanelRect.gameObject : null;
|
||||||
|
im.inventoryCanvas = canvas;
|
||||||
|
|
||||||
|
// Скрыть панель инвентаря по умолчанию
|
||||||
|
if (im.inventoryPanel != null)
|
||||||
|
im.inventoryPanel.SetActive(false);
|
||||||
|
|
||||||
|
// ── PlayerInput (дочерний объект Player) ──────────────────────────────
|
||||||
|
var piGO = new GameObject("PlayerInput");
|
||||||
|
piGO.transform.SetParent(player.transform, false);
|
||||||
|
var pi = piGO.AddComponent<PlayerInput>();
|
||||||
|
var inputActions = AssetDatabase.LoadAssetAtPath<UnityEngine.InputSystem.InputActionAsset>(
|
||||||
|
"Assets/Input/PlayerControls.inputactions");
|
||||||
|
if (inputActions != null)
|
||||||
|
pi.actions = inputActions;
|
||||||
|
else
|
||||||
|
Debug.LogWarning("[Setup] Назначьте Assets/Input/PlayerControls.inputactions на компонент PlayerInput вручную.");
|
||||||
|
|
||||||
|
// ── HandEquipSystem ───────────────────────────────────────────────────
|
||||||
|
player.AddComponent<HandEquipSystem>();
|
||||||
|
|
||||||
|
Selection.activeGameObject = player;
|
||||||
|
Debug.Log("[Setup] Готово! Назначьте кость руки (handBone) в HandEquipSystem на Player.");
|
||||||
|
}
|
||||||
|
|
||||||
|
// ── Вспомогательные методы ────────────────────────────────────────────────
|
||||||
|
|
||||||
|
static GameObject CreatePlayerGO()
|
||||||
{
|
{
|
||||||
var go = new GameObject("Player");
|
var go = new GameObject("Player");
|
||||||
|
|
||||||
@@ -15,288 +95,39 @@ public class InventorySceneSetup
|
|||||||
cc.radius = 0.5f;
|
cc.radius = 0.5f;
|
||||||
cc.center = new Vector3(0, 0.9f, 0);
|
cc.center = new Vector3(0, 0.9f, 0);
|
||||||
|
|
||||||
var character = go.AddComponent<charecter>();
|
var ch = go.AddComponent<charecter>();
|
||||||
character.walkSpeed = 5f;
|
ch.walkSpeed = 5f;
|
||||||
character.runSpeed = 9f;
|
ch.runSpeed = 9f;
|
||||||
character.crouchSpeed = 2.5f;
|
ch.crouchSpeed = 2.5f;
|
||||||
character.jumpHeight = 1.5f;
|
ch.jumpHeight = 1.5f;
|
||||||
character.gravity = -9.81f;
|
ch.gravity = -9.81f;
|
||||||
|
|
||||||
GameObject body = GameObject.CreatePrimitive(PrimitiveType.Capsule);
|
// Визуальная капсула
|
||||||
|
var body = GameObject.CreatePrimitive(PrimitiveType.Capsule);
|
||||||
body.name = "Body";
|
body.name = "Body";
|
||||||
body.transform.SetParent(go.transform);
|
body.transform.SetParent(go.transform, false);
|
||||||
body.transform.localPosition = Vector3.zero;
|
Object.DestroyImmediate(body.GetComponent<Collider>());
|
||||||
GameObject.Destroy(body.GetComponent<Collider>());
|
|
||||||
|
|
||||||
GameObject head = new GameObject("Head");
|
// Голова
|
||||||
head.transform.SetParent(go.transform);
|
var head = new GameObject("Head");
|
||||||
|
head.transform.SetParent(go.transform, false);
|
||||||
head.transform.localPosition = new Vector3(0, 0.8f, 0);
|
head.transform.localPosition = new Vector3(0, 0.8f, 0);
|
||||||
character.head = head.transform;
|
ch.head = head.transform;
|
||||||
|
|
||||||
GameObject camObj = new GameObject("PlayerCamera");
|
// Камера
|
||||||
camObj.transform.SetParent(head.transform);
|
var camObj = new GameObject("PlayerCamera");
|
||||||
|
camObj.transform.SetParent(head.transform, false);
|
||||||
camObj.transform.localPosition = new Vector3(0, 0.1f, 0);
|
camObj.transform.localPosition = new Vector3(0, 0.1f, 0);
|
||||||
var cam = camObj.AddComponent<Camera>();
|
var cam = camObj.AddComponent<Camera>();
|
||||||
cam.tag = "MainCamera";
|
cam.tag = "MainCamera";
|
||||||
|
cam.nearClipPlane = 0.05f;
|
||||||
|
|
||||||
var existingCam = GameObject.FindGameObjectWithTag("MainCamera");
|
var oldCam = GameObject.FindWithTag("MainCamera");
|
||||||
if (existingCam != null && existingCam != camObj)
|
if (oldCam != null && oldCam != camObj)
|
||||||
{
|
Object.DestroyImmediate(oldCam);
|
||||||
GameObject.Destroy(existingCam);
|
|
||||||
}
|
|
||||||
|
|
||||||
go.tag = "Player";
|
go.tag = "Player";
|
||||||
go.transform.position = new Vector3(0, 2, -5);
|
go.transform.position = new Vector3(0, 2, -5);
|
||||||
|
return go;
|
||||||
Selection.activeGameObject = go;
|
|
||||||
Debug.Log("[Tools] Создан игрок!");
|
|
||||||
}
|
|
||||||
|
|
||||||
[MenuItem("Tools/Create Item Prefab")]
|
|
||||||
public static void CreateItemPrefab()
|
|
||||||
{
|
|
||||||
var itemGO = new GameObject("NewItem");
|
|
||||||
itemGO.AddComponent<WorldItem>();
|
|
||||||
|
|
||||||
var sphere = itemGO.AddComponent<SphereCollider>();
|
|
||||||
sphere.radius = 0.5f;
|
|
||||||
sphere.isTrigger = true;
|
|
||||||
|
|
||||||
var visual = GameObject.CreatePrimitive(PrimitiveType.Cube);
|
|
||||||
visual.name = "Visual";
|
|
||||||
visual.transform.SetParent(itemGO.transform);
|
|
||||||
visual.transform.localPosition = Vector3.zero;
|
|
||||||
visual.transform.localScale = new Vector3(0.3f, 0.3f, 0.3f);
|
|
||||||
GameObject.Destroy(visual.GetComponent<Collider>());
|
|
||||||
|
|
||||||
Selection.activeGameObject = itemGO;
|
|
||||||
Debug.Log("[Tools] Создан префаб предмета!");
|
|
||||||
}
|
|
||||||
|
|
||||||
[MenuItem("Tools/Create Test Item in Scene")]
|
|
||||||
public static void CreateTestItem()
|
|
||||||
{
|
|
||||||
// Создаём тестовый предмет в сцене
|
|
||||||
var itemGO = new GameObject("TestItem");
|
|
||||||
itemGO.transform.position = new Vector3(0, 0.5f, 3);
|
|
||||||
|
|
||||||
// Визуал
|
|
||||||
var visual = GameObject.CreatePrimitive(PrimitiveType.Cube);
|
|
||||||
visual.name = "Visual";
|
|
||||||
visual.transform.SetParent(itemGO.transform);
|
|
||||||
visual.transform.localPosition = Vector3.zero;
|
|
||||||
visual.transform.localScale = Vector3.one * 0.3f;
|
|
||||||
GameObject.Destroy(visual.GetComponent<Collider>());
|
|
||||||
|
|
||||||
// Компонент предмета
|
|
||||||
var worldItem = itemGO.AddComponent<WorldItem>();
|
|
||||||
worldItem.useFactory = false;
|
|
||||||
|
|
||||||
// Тестовые данные
|
|
||||||
var testItem = ScriptableObject.CreateInstance<ItemData>();
|
|
||||||
testItem.id = "test_item";
|
|
||||||
testItem.itemName = "Тестовый предмет";
|
|
||||||
testItem.description = "Просто тестовый предмет";
|
|
||||||
testItem.type = ItemType.Material;
|
|
||||||
testItem.maxStack = 64;
|
|
||||||
|
|
||||||
// Используем Setup чтобы инициализировать визуал и включить мгновенный подбор
|
|
||||||
worldItem.Setup(testItem, 5);
|
|
||||||
|
|
||||||
// Коллайдер для подбора (trigger для обычных коллайдеров)
|
|
||||||
var box = itemGO.AddComponent<BoxCollider>();
|
|
||||||
box.isTrigger = true;
|
|
||||||
box.size = Vector3.one;
|
|
||||||
|
|
||||||
Selection.activeGameObject = itemGO;
|
|
||||||
Debug.Log("[Tools] Создан тестовый предмет! Подойдите к нему игроком.");
|
|
||||||
}
|
|
||||||
|
|
||||||
[MenuItem("Tools/Setup Inventory Scene")]
|
|
||||||
public static void SetupScene()
|
|
||||||
{
|
|
||||||
var scene = UnityEngine.SceneManagement.SceneManager.GetActiveScene();
|
|
||||||
var rootObjects = scene.GetRootGameObjects();
|
|
||||||
|
|
||||||
foreach (var root in rootObjects)
|
|
||||||
{
|
|
||||||
if (root.GetComponent<InventoryManager>() != null)
|
|
||||||
{
|
|
||||||
Debug.LogWarning("InventoryManager уже существует!");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Создаём GameManager
|
|
||||||
var gameManager = new GameObject("GameManager");
|
|
||||||
var im = gameManager.AddComponent<InventoryManager>();
|
|
||||||
gameManager.AddComponent<InventoryExampleItems>();
|
|
||||||
gameManager.AddComponent<InventoryTester>();
|
|
||||||
|
|
||||||
// Создаём Canvas
|
|
||||||
var canvasGO = new GameObject("InventoryCanvas");
|
|
||||||
var canvas = canvasGO.AddComponent<Canvas>();
|
|
||||||
canvas.renderMode = RenderMode.ScreenSpaceOverlay;
|
|
||||||
canvas.sortingOrder = 100;
|
|
||||||
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 inventoryRect = inventoryPanel.GetComponent<RectTransform>();
|
|
||||||
SetRect(inventoryRect, new Vector2(0.5f, 0.5f), new Vector2(0.5f, 0.5f), Vector2.zero, new Vector2(500, 300));
|
|
||||||
|
|
||||||
// Заголовок
|
|
||||||
CreateTitle(inventoryPanel.transform, "Инвентарь", new Vector2(0, 130));
|
|
||||||
|
|
||||||
// Сетка инвентаря (4x9 = 36 слотов)
|
|
||||||
var inventoryGrid = CreateGrid(inventoryPanel.transform, "InventoryGrid", 9, 4, 50, 4, new Vector2(10, 40));
|
|
||||||
im.slots = CreateSlots(inventoryGrid, "InventorySlot_", 0, 36);
|
|
||||||
|
|
||||||
// Создаём хотбар
|
|
||||||
var hotbarPanel = CreatePanel(canvasGO.transform, "HotbarPanel", new Color(0.1f, 0.1f, 0.1f, 0.9f));
|
|
||||||
var hotbarRect = hotbarPanel.GetComponent<RectTransform>();
|
|
||||||
SetRect(hotbarRect, new Vector2(0.5f, 0f), new Vector2(0.5f, 0f), new Vector2(0, 15), new Vector2(460, 60));
|
|
||||||
|
|
||||||
var hotbarGrid = CreateGrid(hotbarPanel.transform, "HotbarGrid", 9, 1, 50, 4, new Vector2(10, 10));
|
|
||||||
im.hotbarSlots = CreateSlots(hotbarGrid, "HotbarSlot_", 0, 9);
|
|
||||||
|
|
||||||
// Подключаем ссылку на панель
|
|
||||||
im.inventoryPanel = inventoryPanel;
|
|
||||||
im.inventoryCanvas = canvas;
|
|
||||||
|
|
||||||
// Скрываем панель
|
|
||||||
inventoryPanel.SetActive(false);
|
|
||||||
|
|
||||||
Debug.Log("[Tools] Инвентарь настроен! (36 слотов + 9 хотбар)");
|
|
||||||
}
|
|
||||||
|
|
||||||
static GameObject CreatePanel(Transform parent, string name, Color color)
|
|
||||||
{
|
|
||||||
var panel = new GameObject(name);
|
|
||||||
panel.transform.SetParent(parent, false);
|
|
||||||
panel.AddComponent<RectTransform>();
|
|
||||||
panel.AddComponent<Image>().color = color;
|
|
||||||
return panel;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void SetRect(RectTransform rect, Vector2 anchorMin, Vector2 anchorMax, Vector2 anchoredPosition, Vector2 sizeDelta)
|
|
||||||
{
|
|
||||||
rect.anchorMin = anchorMin;
|
|
||||||
rect.anchorMax = anchorMax;
|
|
||||||
rect.pivot = new Vector2(0.5f, 0.5f);
|
|
||||||
rect.anchoredPosition = anchoredPosition;
|
|
||||||
rect.sizeDelta = sizeDelta;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void CreateTitle(Transform parent, string text, Vector2 position)
|
|
||||||
{
|
|
||||||
var titleObj = new GameObject("Title");
|
|
||||||
titleObj.transform.SetParent(parent, false);
|
|
||||||
var rect = titleObj.AddComponent<RectTransform>();
|
|
||||||
rect.anchorMin = new Vector2(0, 1);
|
|
||||||
rect.anchorMax = new Vector2(1, 1);
|
|
||||||
rect.pivot = new Vector2(0.5f, 1);
|
|
||||||
rect.anchoredPosition = position;
|
|
||||||
rect.sizeDelta = new Vector2(-20, 30);
|
|
||||||
|
|
||||||
var tmp = titleObj.AddComponent<TextMeshProUGUI>();
|
|
||||||
tmp.text = text;
|
|
||||||
tmp.fontSize = 18;
|
|
||||||
tmp.alignment = TextAlignmentOptions.Center;
|
|
||||||
tmp.color = Color.white;
|
|
||||||
}
|
|
||||||
|
|
||||||
static Transform CreateGrid(Transform parent, string name, int cols, int rows, float cellSize, float spacing, Vector2 offset)
|
|
||||||
{
|
|
||||||
var gridObj = new GameObject(name);
|
|
||||||
gridObj.transform.SetParent(parent, false);
|
|
||||||
var rect = gridObj.AddComponent<RectTransform>();
|
|
||||||
rect.anchorMin = Vector2.zero;
|
|
||||||
rect.anchorMax = Vector2.one;
|
|
||||||
rect.offsetMin = offset;
|
|
||||||
rect.offsetMax = -offset;
|
|
||||||
|
|
||||||
var grid = gridObj.AddComponent<GridLayoutGroup>();
|
|
||||||
grid.cellSize = new Vector2(cellSize, cellSize);
|
|
||||||
grid.spacing = new Vector2(spacing, spacing);
|
|
||||||
grid.startCorner = GridLayoutGroup.Corner.UpperLeft;
|
|
||||||
grid.startAxis = GridLayoutGroup.Axis.Horizontal;
|
|
||||||
grid.constraint = GridLayoutGroup.Constraint.FixedColumnCount;
|
|
||||||
grid.constraintCount = cols;
|
|
||||||
|
|
||||||
return gridObj.transform;
|
|
||||||
}
|
|
||||||
|
|
||||||
static Slot[] CreateSlots(Transform parent, string prefix, int startIndex, int count)
|
|
||||||
{
|
|
||||||
var slots = new Slot[count];
|
|
||||||
var slotSize = 50f;
|
|
||||||
var emptyColor = new Color(0.25f, 0.25f, 0.25f, 0.8f);
|
|
||||||
|
|
||||||
for (int i = 0; i < count; i++)
|
|
||||||
{
|
|
||||||
var slotObj = new GameObject(prefix + (startIndex + i));
|
|
||||||
slotObj.transform.SetParent(parent, false);
|
|
||||||
slotObj.AddComponent<RectTransform>().sizeDelta = new Vector2(slotSize, slotSize);
|
|
||||||
|
|
||||||
var bg = slotObj.AddComponent<Image>();
|
|
||||||
bg.color = emptyColor;
|
|
||||||
|
|
||||||
var slot = slotObj.AddComponent<Slot>();
|
|
||||||
slot.slotIndex = startIndex + i;
|
|
||||||
|
|
||||||
// Icon
|
|
||||||
var iconObj = new GameObject("Icon");
|
|
||||||
iconObj.transform.SetParent(slotObj.transform, false);
|
|
||||||
var iconRect = iconObj.AddComponent<RectTransform>();
|
|
||||||
iconRect.anchorMin = Vector2.zero;
|
|
||||||
iconRect.anchorMax = Vector2.one;
|
|
||||||
iconRect.offsetMin = new Vector2(4, 4);
|
|
||||||
iconRect.offsetMax = new Vector2(-4, -4);
|
|
||||||
slot.iconImage = iconObj.AddComponent<Image>();
|
|
||||||
slot.iconImage.preserveAspect = true;
|
|
||||||
slot.iconImage.enabled = false;
|
|
||||||
|
|
||||||
// Amount panel
|
|
||||||
var amountObj = new GameObject("AmountPanel");
|
|
||||||
amountObj.transform.SetParent(slotObj.transform, false);
|
|
||||||
var amountRect = amountObj.AddComponent<RectTransform>();
|
|
||||||
amountRect.anchorMin = Vector2.one;
|
|
||||||
amountRect.anchorMax = Vector2.one;
|
|
||||||
amountRect.pivot = new Vector2(1, 0);
|
|
||||||
amountRect.anchoredPosition = new Vector2(-2, 2);
|
|
||||||
amountRect.sizeDelta = new Vector2(22, 22);
|
|
||||||
slot.amountPanel = amountObj;
|
|
||||||
slot.amountPanel.SetActive(false);
|
|
||||||
|
|
||||||
amountObj.AddComponent<Image>().color = new Color(0, 0, 0, 0.7f);
|
|
||||||
|
|
||||||
var amountTextObj = new GameObject("Text");
|
|
||||||
amountTextObj.transform.SetParent(amountObj.transform, false);
|
|
||||||
amountTextObj.AddComponent<RectTransform>().sizeDelta = new Vector2(20, 20);
|
|
||||||
slot.amountText = amountTextObj.AddComponent<TextMeshProUGUI>();
|
|
||||||
slot.amountText.fontSize = 14;
|
|
||||||
slot.amountText.alignment = TextAlignmentOptions.Right;
|
|
||||||
slot.amountText.color = Color.white;
|
|
||||||
slot.amountText.fontStyle = FontStyles.Bold;
|
|
||||||
|
|
||||||
// Drag & Drop
|
|
||||||
var dragDrop = slotObj.AddComponent<InventoryDragDrop>();
|
|
||||||
dragDrop.slot = slot;
|
|
||||||
dragDrop.slotIndex = slot.slotIndex;
|
|
||||||
|
|
||||||
slots[i] = slot;
|
|
||||||
}
|
|
||||||
|
|
||||||
return slots;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1,101 +0,0 @@
|
|||||||
#if UNITY_EDITOR
|
|
||||||
using UnityEditor;
|
|
||||||
#endif
|
|
||||||
using UnityEngine;
|
|
||||||
using UnityEngine.UI;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Автоматически настраивает всю систему инвентаря на сцене
|
|
||||||
/// Добавить на пустой GameObject "GameManager" в сцене
|
|
||||||
/// </summary>
|
|
||||||
public class InventorySetup : MonoBehaviour
|
|
||||||
{
|
|
||||||
[Header("Настройки")]
|
|
||||||
public bool createUI = true;
|
|
||||||
public bool createManagers = true;
|
|
||||||
|
|
||||||
void Awake()
|
|
||||||
{
|
|
||||||
// Не создаём если уже есть на сцене (после ручной настройки)
|
|
||||||
if (FindObjectOfType<InventoryManager>() != null)
|
|
||||||
{
|
|
||||||
Debug.Log("[InventorySetup] Inventory already exists, skipping creation");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (createManagers)
|
|
||||||
SetupManagers();
|
|
||||||
|
|
||||||
if (createUI)
|
|
||||||
SetupUI();
|
|
||||||
}
|
|
||||||
|
|
||||||
void SetupManagers()
|
|
||||||
{
|
|
||||||
var imGO = new GameObject("InventoryManager");
|
|
||||||
imGO.transform.SetParent(transform);
|
|
||||||
imGO.AddComponent<InventoryManager>();
|
|
||||||
|
|
||||||
var itemsGO = new GameObject("InventoryItems");
|
|
||||||
itemsGO.transform.SetParent(transform);
|
|
||||||
itemsGO.AddComponent<InventoryExampleItems>();
|
|
||||||
|
|
||||||
var testerGO = new GameObject("InventoryTester");
|
|
||||||
testerGO.transform.SetParent(transform);
|
|
||||||
testerGO.AddComponent<InventoryTester>();
|
|
||||||
|
|
||||||
Debug.Log("[InventorySetup] Managers created");
|
|
||||||
}
|
|
||||||
|
|
||||||
void SetupUI()
|
|
||||||
{
|
|
||||||
var canvasGO = new GameObject("InventoryCanvas");
|
|
||||||
canvasGO.transform.SetParent(transform);
|
|
||||||
|
|
||||||
var canvas = canvasGO.AddComponent<Canvas>();
|
|
||||||
canvas.renderMode = RenderMode.ScreenSpaceOverlay;
|
|
||||||
canvas.sortingOrder = 100;
|
|
||||||
canvasGO.AddComponent<GraphicRaycaster>();
|
|
||||||
|
|
||||||
canvasGO.AddComponent<InventoryUIBuilder>();
|
|
||||||
|
|
||||||
Debug.Log("[InventorySetup] UI created");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#if UNITY_EDITOR
|
|
||||||
/// <summary>
|
|
||||||
/// Кнопка в инспекторе для быстрой настройки сцены
|
|
||||||
/// </summary>
|
|
||||||
[CustomEditor(typeof(InventorySetup))]
|
|
||||||
public class InventorySetupEditor : Editor
|
|
||||||
{
|
|
||||||
public override void OnInspectorGUI()
|
|
||||||
{
|
|
||||||
base.OnInspectorGUI();
|
|
||||||
|
|
||||||
if (GUILayout.Button("Настроить сцену для инвентаря"))
|
|
||||||
{
|
|
||||||
var target = (InventorySetup)this.target;
|
|
||||||
|
|
||||||
if (FindObjectOfType<InventoryManager>() == null)
|
|
||||||
{
|
|
||||||
target.createManagers = true;
|
|
||||||
target.createUI = true;
|
|
||||||
Debug.Log("Инвентарь будет настроен при запуске");
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
Debug.LogWarning("InventoryManager уже существует на сцене!");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
GUILayout.Space(10);
|
|
||||||
|
|
||||||
if (GUILayout.Button("Открыть сцену в Unity"))
|
|
||||||
{
|
|
||||||
EditorApplication.ExecuteMenuItem("Window/General/Scene");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
@@ -1,2 +0,0 @@
|
|||||||
fileFormatVersion: 2
|
|
||||||
guid: 9a832ca7ed419e6479e1cc308a222f33
|
|
||||||
@@ -3,7 +3,9 @@ using UnityEngine.UI;
|
|||||||
using TMPro;
|
using TMPro;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Создаёт UI инвентаря программно с использованием TextMeshPro
|
/// Создаёт UI инвентаря программно.
|
||||||
|
/// Вызывается ТОЛЬКО из редакторных инструментов (InventorySceneSetup, PlayerBuilderTool).
|
||||||
|
/// Никакого runtime-создания: Start() отсутствует.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public class InventoryUIBuilder : MonoBehaviour
|
public class InventoryUIBuilder : MonoBehaviour
|
||||||
{
|
{
|
||||||
@@ -22,30 +24,24 @@ public class InventoryUIBuilder : MonoBehaviour
|
|||||||
[SerializeField] private Color inventoryPanelColor = new Color(0.15f, 0.15f, 0.15f, 0.95f);
|
[SerializeField] private Color inventoryPanelColor = new Color(0.15f, 0.15f, 0.15f, 0.95f);
|
||||||
[SerializeField] private Color hotbarPanelColor = new Color(0.1f, 0.1f, 0.1f, 0.9f);
|
[SerializeField] private Color hotbarPanelColor = new Color(0.1f, 0.1f, 0.1f, 0.9f);
|
||||||
[SerializeField] private Color slotEmptyColor = new Color(0.25f, 0.25f, 0.25f, 0.8f);
|
[SerializeField] private Color slotEmptyColor = new Color(0.25f, 0.25f, 0.25f, 0.8f);
|
||||||
[SerializeField] private Color slotFilledColor = new Color(0.35f, 0.35f, 0.35f, 0.95f);
|
|
||||||
|
|
||||||
[Header("Container References")]
|
[Header("Container References")]
|
||||||
public RectTransform inventoryPanelRect;
|
public RectTransform inventoryPanelRect;
|
||||||
public RectTransform hotbarPanelRect;
|
public RectTransform hotbarPanelRect;
|
||||||
public Canvas inventoryCanvas;
|
public Canvas inventoryCanvas;
|
||||||
|
|
||||||
void Start()
|
// Созданные слоты — читаются редакторным инструментом после BuildInventoryUI()
|
||||||
{
|
[SerializeField] private Slot[] _inventorySlots;
|
||||||
// Проверяем, не запущен ли уже BuildInventoryUI
|
[SerializeField] private Slot[] _hotbarSlots;
|
||||||
if (InventoryManager.Instance != null &&
|
|
||||||
InventoryManager.Instance.slots != null &&
|
|
||||||
InventoryManager.Instance.slots.Length > 0)
|
|
||||||
{
|
|
||||||
Debug.Log("[InventoryUIBuilder] UI already built, skipping");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
BuildInventoryUI();
|
public Slot[] GetInventorySlots() => _inventorySlots;
|
||||||
}
|
public Slot[] GetHotbarSlots() => _hotbarSlots;
|
||||||
|
|
||||||
|
// ── Построение UI ────────────────────────────────────────────────────────
|
||||||
|
|
||||||
public void BuildInventoryUI()
|
public void BuildInventoryUI()
|
||||||
{
|
{
|
||||||
// Создаём или получаем Canvas
|
// Получаем или добавляем Canvas
|
||||||
var canvas = GetComponent<Canvas>();
|
var canvas = GetComponent<Canvas>();
|
||||||
if (canvas == null)
|
if (canvas == null)
|
||||||
{
|
{
|
||||||
@@ -56,18 +52,12 @@ public class InventoryUIBuilder : MonoBehaviour
|
|||||||
}
|
}
|
||||||
inventoryCanvas = canvas;
|
inventoryCanvas = canvas;
|
||||||
|
|
||||||
// Настраиваем EventSystem если нет
|
// Панель инвентаря
|
||||||
if (FindObjectOfType<TMPro.TMP_InputField>() != null || FindObjectsOfType<TMPro.TextMeshProUGUI>().Length > 0)
|
|
||||||
{
|
|
||||||
// EventSystem уже есть
|
|
||||||
}
|
|
||||||
|
|
||||||
// Создаём панель инвентаря
|
|
||||||
GameObject inventoryPanel = CreatePanel("InventoryPanel", transform, inventoryPanelColor);
|
GameObject inventoryPanel = CreatePanel("InventoryPanel", transform, inventoryPanelColor);
|
||||||
inventoryPanelRect = inventoryPanel.GetComponent<RectTransform>();
|
inventoryPanelRect = inventoryPanel.GetComponent<RectTransform>();
|
||||||
|
|
||||||
float inventoryWidth = inventoryCols * (slotSize + slotSpacing) + inventoryPadding * 2;
|
float inventoryWidth = inventoryCols * (slotSize + slotSpacing) + inventoryPadding * 2;
|
||||||
float inventoryHeight = inventoryRows * (slotSize + slotSpacing) + inventoryPadding * 2 + 40; // +40 для заголовка
|
float inventoryHeight = inventoryRows * (slotSize + slotSpacing) + inventoryPadding * 2 + 40;
|
||||||
|
|
||||||
inventoryPanelRect.anchorMin = new Vector2(0.5f, 0.5f);
|
inventoryPanelRect.anchorMin = new Vector2(0.5f, 0.5f);
|
||||||
inventoryPanelRect.anchorMax = new Vector2(0.5f, 0.5f);
|
inventoryPanelRect.anchorMax = new Vector2(0.5f, 0.5f);
|
||||||
@@ -75,23 +65,17 @@ public class InventoryUIBuilder : MonoBehaviour
|
|||||||
inventoryPanelRect.anchoredPosition = Vector2.zero;
|
inventoryPanelRect.anchoredPosition = Vector2.zero;
|
||||||
inventoryPanelRect.sizeDelta = new Vector2(inventoryWidth, inventoryHeight);
|
inventoryPanelRect.sizeDelta = new Vector2(inventoryWidth, inventoryHeight);
|
||||||
|
|
||||||
// Заголовок
|
|
||||||
CreateTitle(inventoryPanel.transform, "Инвентарь", new Vector2(0, inventoryHeight / 2 - 20));
|
CreateTitle(inventoryPanel.transform, "Инвентарь", new Vector2(0, inventoryHeight / 2 - 20));
|
||||||
|
|
||||||
// Сетка инвентаря (4x9 = 36 слотов)
|
|
||||||
float gridHeight = inventoryRows * (slotSize + slotSpacing);
|
|
||||||
var inventoryGrid = CreateGrid(
|
var inventoryGrid = CreateGrid(
|
||||||
inventoryPanel.transform,
|
inventoryPanel.transform, "InventoryGrid",
|
||||||
"InventoryGrid",
|
inventoryCols, inventoryRows,
|
||||||
inventoryCols,
|
slotSize, slotSpacing,
|
||||||
inventoryRows,
|
new Vector2(inventoryPadding, inventoryPadding + 30));
|
||||||
slotSize,
|
|
||||||
slotSpacing,
|
|
||||||
new Vector2(inventoryPadding, inventoryPadding + 30)
|
|
||||||
);
|
|
||||||
InventoryManager.Instance.slots = CreateSlots(inventoryGrid, "InventorySlot_", 0, inventoryCols * inventoryRows);
|
|
||||||
|
|
||||||
// Создаём хотбар
|
_inventorySlots = CreateSlots(inventoryGrid, "InventorySlot_", 0, inventoryCols * inventoryRows);
|
||||||
|
|
||||||
|
// Хотбар
|
||||||
GameObject hotbarPanel = CreatePanel("HotbarPanel", transform, hotbarPanelColor);
|
GameObject hotbarPanel = CreatePanel("HotbarPanel", transform, hotbarPanelColor);
|
||||||
hotbarPanelRect = hotbarPanel.GetComponent<RectTransform>();
|
hotbarPanelRect = hotbarPanel.GetComponent<RectTransform>();
|
||||||
|
|
||||||
@@ -104,37 +88,30 @@ public class InventoryUIBuilder : MonoBehaviour
|
|||||||
hotbarPanelRect.sizeDelta = new Vector2(hotbarWidth, slotSize + hotbarPadding * 2);
|
hotbarPanelRect.sizeDelta = new Vector2(hotbarWidth, slotSize + hotbarPadding * 2);
|
||||||
|
|
||||||
var hotbarGrid = CreateGrid(
|
var hotbarGrid = CreateGrid(
|
||||||
hotbarPanel.transform,
|
hotbarPanel.transform, "HotbarGrid",
|
||||||
"HotbarGrid",
|
hotbarSlots, 1,
|
||||||
hotbarSlots,
|
slotSize, slotSpacing,
|
||||||
1,
|
new Vector2(hotbarPadding, hotbarPadding));
|
||||||
slotSize,
|
|
||||||
slotSpacing,
|
|
||||||
new Vector2(hotbarPadding, hotbarPadding)
|
|
||||||
);
|
|
||||||
InventoryManager.Instance.hotbarSlots = CreateSlots(hotbarGrid, "HotbarSlot_", 0, hotbarSlots);
|
|
||||||
|
|
||||||
// Настраиваем InventoryManager
|
_hotbarSlots = CreateSlots(hotbarGrid, "HotbarSlot_", 0, hotbarSlots);
|
||||||
InventoryManager.Instance.inventoryPanel = inventoryPanel;
|
|
||||||
InventoryManager.Instance.inventoryCanvas = inventoryCanvas;
|
|
||||||
|
|
||||||
Debug.Log($"[InventoryUIBuilder] Created {inventoryCols * inventoryRows} inventory slots + {hotbarSlots} hotbar slots");
|
Debug.Log($"[InventoryUIBuilder] Built {inventoryCols * inventoryRows} inventory slots + {hotbarSlots} hotbar slots");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ── Вспомогательные методы ────────────────────────────────────────────────
|
||||||
|
|
||||||
GameObject CreatePanel(string name, Transform parent, Color color)
|
GameObject CreatePanel(string name, Transform parent, Color color)
|
||||||
{
|
{
|
||||||
GameObject panel = new GameObject(name);
|
var panel = new GameObject(name);
|
||||||
panel.transform.SetParent(parent, false);
|
panel.transform.SetParent(parent, false);
|
||||||
|
panel.AddComponent<RectTransform>();
|
||||||
var rect = panel.AddComponent<RectTransform>();
|
|
||||||
panel.AddComponent<Image>().color = color;
|
panel.AddComponent<Image>().color = color;
|
||||||
|
|
||||||
return panel;
|
return panel;
|
||||||
}
|
}
|
||||||
|
|
||||||
void CreateTitle(Transform parent, string text, Vector2 position)
|
void CreateTitle(Transform parent, string text, Vector2 position)
|
||||||
{
|
{
|
||||||
GameObject titleObj = new GameObject("Title");
|
var titleObj = new GameObject("Title");
|
||||||
titleObj.transform.SetParent(parent, false);
|
titleObj.transform.SetParent(parent, false);
|
||||||
|
|
||||||
var rect = titleObj.AddComponent<RectTransform>();
|
var rect = titleObj.AddComponent<RectTransform>();
|
||||||
@@ -153,7 +130,7 @@ public class InventoryUIBuilder : MonoBehaviour
|
|||||||
|
|
||||||
Transform CreateGrid(Transform parent, string name, int cols, int rows, float cellSize, float spacing, Vector2 offset)
|
Transform CreateGrid(Transform parent, string name, int cols, int rows, float cellSize, float spacing, Vector2 offset)
|
||||||
{
|
{
|
||||||
GameObject gridObj = new GameObject(name);
|
var gridObj = new GameObject(name);
|
||||||
gridObj.transform.SetParent(parent, false);
|
gridObj.transform.SetParent(parent, false);
|
||||||
|
|
||||||
var rect = gridObj.AddComponent<RectTransform>();
|
var rect = gridObj.AddComponent<RectTransform>();
|
||||||
@@ -180,22 +157,21 @@ public class InventoryUIBuilder : MonoBehaviour
|
|||||||
|
|
||||||
for (int i = 0; i < count; i++)
|
for (int i = 0; i < count; i++)
|
||||||
{
|
{
|
||||||
GameObject slotObj = new GameObject(prefix + (startIndex + i));
|
var slotObj = new GameObject(prefix + (startIndex + i));
|
||||||
slotObj.transform.SetParent(parent, false);
|
slotObj.transform.SetParent(parent, false);
|
||||||
|
|
||||||
var rect = slotObj.AddComponent<RectTransform>();
|
var rect = slotObj.AddComponent<RectTransform>();
|
||||||
rect.sizeDelta = new Vector2(slotSize, slotSize);
|
rect.sizeDelta = new Vector2(slotSize, slotSize);
|
||||||
|
|
||||||
// Background
|
|
||||||
var bg = slotObj.AddComponent<Image>();
|
var bg = slotObj.AddComponent<Image>();
|
||||||
bg.color = slotEmptyColor;
|
bg.color = slotEmptyColor;
|
||||||
|
|
||||||
// Slot компонент
|
|
||||||
var slot = slotObj.AddComponent<Slot>();
|
var slot = slotObj.AddComponent<Slot>();
|
||||||
slot.slotIndex = startIndex + i;
|
slot.slotIndex = startIndex + i;
|
||||||
|
slot.slotBackground = bg;
|
||||||
|
|
||||||
// Icon
|
// Иконка
|
||||||
GameObject iconObj = new GameObject("Icon");
|
var iconObj = new GameObject("Icon");
|
||||||
iconObj.transform.SetParent(slotObj.transform, false);
|
iconObj.transform.SetParent(slotObj.transform, false);
|
||||||
var iconRect = iconObj.AddComponent<RectTransform>();
|
var iconRect = iconObj.AddComponent<RectTransform>();
|
||||||
iconRect.anchorMin = Vector2.zero;
|
iconRect.anchorMin = Vector2.zero;
|
||||||
@@ -206,8 +182,8 @@ public class InventoryUIBuilder : MonoBehaviour
|
|||||||
slot.iconImage.preserveAspect = true;
|
slot.iconImage.preserveAspect = true;
|
||||||
slot.iconImage.enabled = false;
|
slot.iconImage.enabled = false;
|
||||||
|
|
||||||
// Amount panel
|
// Количество
|
||||||
GameObject amountObj = new GameObject("AmountPanel");
|
var amountObj = new GameObject("AmountPanel");
|
||||||
amountObj.transform.SetParent(slotObj.transform, false);
|
amountObj.transform.SetParent(slotObj.transform, false);
|
||||||
var amountRect = amountObj.AddComponent<RectTransform>();
|
var amountRect = amountObj.AddComponent<RectTransform>();
|
||||||
amountRect.anchorMin = Vector2.one;
|
amountRect.anchorMin = Vector2.one;
|
||||||
@@ -217,10 +193,9 @@ public class InventoryUIBuilder : MonoBehaviour
|
|||||||
amountRect.sizeDelta = new Vector2(22, 22);
|
amountRect.sizeDelta = new Vector2(22, 22);
|
||||||
slot.amountPanel = amountObj;
|
slot.amountPanel = amountObj;
|
||||||
|
|
||||||
var amountBg = amountObj.AddComponent<Image>();
|
amountObj.AddComponent<Image>().color = new Color(0, 0, 0, 0.7f);
|
||||||
amountBg.color = new Color(0, 0, 0, 0.7f);
|
|
||||||
|
|
||||||
GameObject amountTextObj = new GameObject("Text");
|
var amountTextObj = new GameObject("Text");
|
||||||
amountTextObj.transform.SetParent(amountObj.transform, false);
|
amountTextObj.transform.SetParent(amountObj.transform, false);
|
||||||
var amountTextRect = amountTextObj.AddComponent<RectTransform>();
|
var amountTextRect = amountTextObj.AddComponent<RectTransform>();
|
||||||
amountTextRect.anchorMin = Vector2.zero;
|
amountTextRect.anchorMin = Vector2.zero;
|
||||||
@@ -231,16 +206,13 @@ public class InventoryUIBuilder : MonoBehaviour
|
|||||||
slot.amountText.color = Color.white;
|
slot.amountText.color = Color.white;
|
||||||
slot.amountText.fontStyle = FontStyles.Bold;
|
slot.amountText.fontStyle = FontStyles.Bold;
|
||||||
|
|
||||||
// Применяем настройки через сеттер
|
|
||||||
slot.amountPanel.SetActive(false);
|
slot.amountPanel.SetActive(false);
|
||||||
slot.slotBackground = bg;
|
|
||||||
|
|
||||||
// Drag & Drop
|
// Drag & Drop
|
||||||
var dragDrop = slotObj.AddComponent<InventoryDragDrop>();
|
var dragDrop = slotObj.AddComponent<InventoryDragDrop>();
|
||||||
dragDrop.slot = slot;
|
dragDrop.slot = slot;
|
||||||
dragDrop.slotIndex = slot.slotIndex;
|
dragDrop.slotIndex = slot.slotIndex;
|
||||||
|
|
||||||
// Подписка на события слота
|
|
||||||
slot.OnSlotClicked += OnSlotClicked;
|
slot.OnSlotClicked += OnSlotClicked;
|
||||||
|
|
||||||
slots[i] = slot;
|
slots[i] = slot;
|
||||||
@@ -249,40 +221,35 @@ public class InventoryUIBuilder : MonoBehaviour
|
|||||||
return slots;
|
return slots;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ── Выделение слота (runtime) ─────────────────────────────────────────────
|
||||||
|
|
||||||
private int _selectedSlot = -1;
|
private int _selectedSlot = -1;
|
||||||
|
|
||||||
private void OnSlotClicked(Slot slot)
|
private void OnSlotClicked(Slot slot)
|
||||||
{
|
{
|
||||||
// Снимаем выделение с предыдущего
|
if (_selectedSlot >= 0 && _inventorySlots != null && _selectedSlot < _inventorySlots.Length)
|
||||||
if (_selectedSlot >= 0 && _selectedSlot < InventoryManager.Instance.slots.Length)
|
_inventorySlots[_selectedSlot].SetSelected(false);
|
||||||
{
|
|
||||||
InventoryManager.Instance.slots[_selectedSlot].SetSelected(false);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Выделяем новый
|
|
||||||
slot.SetSelected(true);
|
slot.SetSelected(true);
|
||||||
_selectedSlot = slot.slotIndex;
|
_selectedSlot = slot.slotIndex;
|
||||||
|
|
||||||
Debug.Log($"[UI] Selected slot: {_selectedSlot} - {slot.GetItem()?.itemName ?? "Empty"}");
|
Debug.Log($"[UI] Selected slot: {_selectedSlot} - {slot.GetItem()?.itemName ?? "Empty"}");
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
// ── Утилиты ───────────────────────────────────────────────────────────────
|
||||||
/// Пересоздать UI (например, при изменении настроек)
|
|
||||||
/// </summary>
|
|
||||||
public void Rebuild()
|
public void Rebuild()
|
||||||
{
|
{
|
||||||
// Удаляем старые панели
|
|
||||||
if (inventoryPanelRect != null)
|
if (inventoryPanelRect != null)
|
||||||
Destroy(inventoryPanelRect.gameObject);
|
Destroy(inventoryPanelRect.gameObject);
|
||||||
if (hotbarPanelRect != null)
|
if (hotbarPanelRect != null)
|
||||||
Destroy(hotbarPanelRect.gameObject);
|
Destroy(hotbarPanelRect.gameObject);
|
||||||
|
|
||||||
|
_inventorySlots = null;
|
||||||
|
_hotbarSlots = null;
|
||||||
BuildInventoryUI();
|
BuildInventoryUI();
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Показать/скрыть инвентарь
|
|
||||||
/// </summary>
|
|
||||||
public void ToggleInventory(bool show)
|
public void ToggleInventory(bool show)
|
||||||
{
|
{
|
||||||
if (inventoryPanelRect != null)
|
if (inventoryPanelRect != null)
|
||||||
|
|||||||
@@ -1,8 +1,11 @@
|
|||||||
using UnityEngine;
|
using UnityEngine;
|
||||||
using UnityEngine.UI;
|
|
||||||
using UnityEditor;
|
using UnityEditor;
|
||||||
using TMPro;
|
using TMPro;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Инструмент создания предметов.
|
||||||
|
/// Tools > Item Builder
|
||||||
|
/// </summary>
|
||||||
public class ItemBuilderTool : EditorWindow
|
public class ItemBuilderTool : EditorWindow
|
||||||
{
|
{
|
||||||
// Основные данные
|
// Основные данные
|
||||||
@@ -23,8 +26,8 @@ public class ItemBuilderTool : EditorWindow
|
|||||||
private bool isDroppable = true;
|
private bool isDroppable = true;
|
||||||
private bool isStackable = true;
|
private bool isStackable = true;
|
||||||
|
|
||||||
// Префаб
|
// Pickup
|
||||||
private GameObject worldItemPrefab;
|
private float interactRange = 2.5f;
|
||||||
|
|
||||||
[MenuItem("Tools/Item Builder")]
|
[MenuItem("Tools/Item Builder")]
|
||||||
public static void ShowWindow()
|
public static void ShowWindow()
|
||||||
@@ -39,7 +42,7 @@ public class ItemBuilderTool : EditorWindow
|
|||||||
// Основные данные
|
// Основные данные
|
||||||
GUILayout.Label("Основное", EditorStyles.miniBoldLabel);
|
GUILayout.Label("Основное", EditorStyles.miniBoldLabel);
|
||||||
itemName = EditorGUILayout.TextField("Название", itemName);
|
itemName = EditorGUILayout.TextField("Название", itemName);
|
||||||
itemId = EditorGUILayout.TextField("ID", itemId);
|
itemId = EditorGUILayout.TextField("ID (оставь пустым для GUID)", itemId);
|
||||||
description = EditorGUILayout.TextField("Описание", description);
|
description = EditorGUILayout.TextField("Описание", description);
|
||||||
itemType = (ItemType)EditorGUILayout.EnumPopup("Тип предмета", itemType);
|
itemType = (ItemType)EditorGUILayout.EnumPopup("Тип предмета", itemType);
|
||||||
|
|
||||||
@@ -47,13 +50,11 @@ public class ItemBuilderTool : EditorWindow
|
|||||||
|
|
||||||
// Визуал
|
// Визуал
|
||||||
GUILayout.Label("Визуал", EditorStyles.miniBoldLabel);
|
GUILayout.Label("Визуал", EditorStyles.miniBoldLabel);
|
||||||
modelPrefab = (GameObject)EditorGUILayout.ObjectField("3D модель", modelPrefab, typeof(GameObject), false);
|
modelPrefab = (GameObject)EditorGUILayout.ObjectField("3D модель (префаб)", modelPrefab, typeof(GameObject), false);
|
||||||
icon = (Sprite)EditorGUILayout.ObjectField("Иконка", icon, typeof(Sprite), false);
|
icon = (Sprite)EditorGUILayout.ObjectField("Иконка", icon, typeof(Sprite), false);
|
||||||
|
|
||||||
if (icon == null)
|
if (icon == null)
|
||||||
{
|
previewColor = EditorGUILayout.ColorField("Цвет иконки (заглушка)", previewColor);
|
||||||
previewColor = EditorGUILayout.ColorField("Цвет иконки", previewColor);
|
|
||||||
}
|
|
||||||
|
|
||||||
GUILayout.Space(10);
|
GUILayout.Space(10);
|
||||||
|
|
||||||
@@ -63,42 +64,36 @@ public class ItemBuilderTool : EditorWindow
|
|||||||
value = EditorGUILayout.IntField("Цена", value);
|
value = EditorGUILayout.IntField("Цена", value);
|
||||||
weight = EditorGUILayout.FloatField("Вес", weight);
|
weight = EditorGUILayout.FloatField("Вес", weight);
|
||||||
isDroppable = EditorGUILayout.Toggle("Можно выбросить", isDroppable);
|
isDroppable = EditorGUILayout.Toggle("Можно выбросить", isDroppable);
|
||||||
isStackable = EditorGUILayout.Toggle("Стек", isStackable);
|
isStackable = EditorGUILayout.Toggle("Стекируемый", isStackable);
|
||||||
|
|
||||||
GUILayout.Space(10);
|
GUILayout.Space(10);
|
||||||
|
|
||||||
// Префаб
|
GUILayout.Label("Подбор", EditorStyles.miniBoldLabel);
|
||||||
GUILayout.Label("Префаб предмета в мире", EditorStyles.miniBoldLabel);
|
interactRange = EditorGUILayout.FloatField("Дальность подбора (E)", interactRange);
|
||||||
worldItemPrefab = (GameObject)EditorGUILayout.ObjectField("WorldItem Prefab", worldItemPrefab, typeof(GameObject), false);
|
|
||||||
|
|
||||||
GUILayout.Space(20);
|
GUILayout.Space(20);
|
||||||
|
|
||||||
// Кнопки
|
// Кнопки
|
||||||
GUI.color = Color.green;
|
GUI.color = Color.green;
|
||||||
if (GUILayout.Button("Создать ItemData"))
|
if (GUILayout.Button("Создать ItemData (ScriptableObject)"))
|
||||||
{
|
|
||||||
CreateItemData();
|
CreateItemData();
|
||||||
}
|
|
||||||
|
|
||||||
GUI.color = Color.cyan;
|
GUI.color = Color.cyan;
|
||||||
if (GUILayout.Button("Создать WorldItem в сцене"))
|
if (GUILayout.Button("Создать WorldItem в сцене"))
|
||||||
{
|
|
||||||
CreateWorldItem();
|
CreateWorldItem();
|
||||||
}
|
|
||||||
|
|
||||||
GUI.color = Color.yellow;
|
GUI.color = Color.yellow;
|
||||||
if (GUILayout.Button("Создать префаб"))
|
if (GUILayout.Button("Создать WorldItem как префаб"))
|
||||||
{
|
|
||||||
CreateItemPrefab();
|
CreateItemPrefab();
|
||||||
}
|
|
||||||
|
|
||||||
GUI.color = Color.white;
|
GUI.color = Color.white;
|
||||||
|
|
||||||
GUILayout.Space(10);
|
GUILayout.Space(10);
|
||||||
EditorGUILayout.HelpBox(
|
EditorGUILayout.HelpBox(
|
||||||
"1. Заполните данные предмета\n" +
|
"Подбор предметов — только по кнопке E (авто-pickup при касании убран намеренно).\n" +
|
||||||
"2. Назначьте модель и иконку\n" +
|
"1. Заполните данные → Создайте ItemData\n" +
|
||||||
"3. Создайте ItemData или префаб",
|
"2. Назначьте ItemData в InventoryManager.itemDatabase\n" +
|
||||||
|
"3. Создайте WorldItem для размещения предметов на сцене",
|
||||||
MessageType.Info);
|
MessageType.Info);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -112,7 +107,7 @@ public class ItemBuilderTool : EditorWindow
|
|||||||
|
|
||||||
var item = ScriptableObject.CreateInstance<ItemData>();
|
var item = ScriptableObject.CreateInstance<ItemData>();
|
||||||
|
|
||||||
item.id = string.IsNullOrEmpty(itemId) ? GUID.Generate().ToString() : itemId;
|
item.id = string.IsNullOrEmpty(itemId) ? System.Guid.NewGuid().ToString() : itemId;
|
||||||
item.itemName = itemName;
|
item.itemName = itemName;
|
||||||
item.description = description;
|
item.description = description;
|
||||||
item.type = itemType;
|
item.type = itemType;
|
||||||
@@ -124,93 +119,89 @@ public class ItemBuilderTool : EditorWindow
|
|||||||
item.isDroppable = isDroppable;
|
item.isDroppable = isDroppable;
|
||||||
item.isStackable = isStackable;
|
item.isStackable = isStackable;
|
||||||
|
|
||||||
// Сохраняем
|
string folder = "Assets/Inventory/Items";
|
||||||
string path = $"Assets/Inventory/Items/{itemName}.asset";
|
|
||||||
string folder = System.IO.Path.GetDirectoryName(path);
|
|
||||||
if (!System.IO.Directory.Exists(folder))
|
if (!System.IO.Directory.Exists(folder))
|
||||||
{
|
|
||||||
System.IO.Directory.CreateDirectory(folder);
|
System.IO.Directory.CreateDirectory(folder);
|
||||||
}
|
|
||||||
|
|
||||||
|
string path = $"{folder}/{itemName}.asset";
|
||||||
AssetDatabase.CreateAsset(item, path);
|
AssetDatabase.CreateAsset(item, path);
|
||||||
AssetDatabase.SaveAssets();
|
AssetDatabase.SaveAssets();
|
||||||
|
|
||||||
Selection.activeObject = item;
|
Selection.activeObject = item;
|
||||||
Debug.Log($"[ItemBuilder] Создан: {itemName}");
|
Debug.Log($"[ItemBuilder] Создан: {itemName} → {path}");
|
||||||
}
|
}
|
||||||
|
|
||||||
void CreateWorldItem()
|
void CreateWorldItem()
|
||||||
{
|
{
|
||||||
if (modelPrefab == null)
|
|
||||||
{
|
|
||||||
// Создаём простой визуал
|
|
||||||
var itemGO = new GameObject(itemName);
|
var itemGO = new GameObject(itemName);
|
||||||
var visual = GameObject.CreatePrimitive(PrimitiveType.Cube);
|
|
||||||
visual.name = "Visual";
|
// Визуал
|
||||||
visual.transform.SetParent(itemGO.transform);
|
GameObject visual;
|
||||||
visual.transform.localPosition = Vector3.zero;
|
if (modelPrefab != null)
|
||||||
|
{
|
||||||
|
visual = (GameObject)PrefabUtility.InstantiatePrefab(modelPrefab, itemGO.transform);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
visual = GameObject.CreatePrimitive(PrimitiveType.Cube);
|
||||||
|
visual.transform.SetParent(itemGO.transform, false);
|
||||||
visual.transform.localScale = Vector3.one * 0.3f;
|
visual.transform.localScale = Vector3.one * 0.3f;
|
||||||
DestroyImmediate(visual.GetComponent<Collider>());
|
DestroyImmediate(visual.GetComponent<Collider>());
|
||||||
|
}
|
||||||
|
visual.name = "Visual";
|
||||||
|
visual.transform.localPosition = Vector3.zero;
|
||||||
|
|
||||||
|
// WorldItem компонент
|
||||||
var worldItem = itemGO.AddComponent<WorldItem>();
|
var worldItem = itemGO.AddComponent<WorldItem>();
|
||||||
|
worldItem.interactRange = interactRange;
|
||||||
|
|
||||||
|
// Trigger-коллайдер для OverlapSphere (не для авто-pickup!)
|
||||||
var col = itemGO.AddComponent<SphereCollider>();
|
var col = itemGO.AddComponent<SphereCollider>();
|
||||||
col.radius = 0.5f;
|
col.radius = 0.5f;
|
||||||
col.isTrigger = true;
|
col.isTrigger = true;
|
||||||
|
|
||||||
itemGO.transform.position = Vector3.zero;
|
itemGO.transform.position = Vector3.zero;
|
||||||
Selection.activeGameObject = itemGO;
|
Selection.activeGameObject = itemGO;
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
var itemGO = Instantiate(modelPrefab);
|
|
||||||
itemGO.name = itemName;
|
|
||||||
itemGO.AddComponent<WorldItem>();
|
|
||||||
itemGO.transform.position = Vector3.zero;
|
|
||||||
Selection.activeGameObject = itemGO;
|
|
||||||
}
|
|
||||||
|
|
||||||
Debug.Log($"[ItemBuilder] Создан WorldItem: {itemName}");
|
Debug.Log($"[ItemBuilder] Создан WorldItem: {itemName}");
|
||||||
}
|
}
|
||||||
|
|
||||||
void CreateItemPrefab()
|
void CreateItemPrefab()
|
||||||
{
|
{
|
||||||
string path = EditorUtility.SaveFilePanelInProject(
|
string path = EditorUtility.SaveFilePanelInProject(
|
||||||
"Сохранить префаб",
|
"Сохранить WorldItem префаб",
|
||||||
itemName,
|
itemName,
|
||||||
"prefab",
|
"prefab",
|
||||||
"Выберите место");
|
"Выберите место сохранения");
|
||||||
|
|
||||||
if (string.IsNullOrEmpty(path)) return;
|
if (string.IsNullOrEmpty(path)) return;
|
||||||
|
|
||||||
GameObject prefab;
|
var prefabGO = new GameObject(itemName);
|
||||||
|
|
||||||
|
// Визуал
|
||||||
|
GameObject visual;
|
||||||
if (modelPrefab != null)
|
if (modelPrefab != null)
|
||||||
{
|
{
|
||||||
prefab = Instantiate(modelPrefab);
|
visual = (GameObject)PrefabUtility.InstantiatePrefab(modelPrefab, prefabGO.transform);
|
||||||
prefab.name = itemName;
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
prefab = new GameObject(itemName);
|
visual = GameObject.CreatePrimitive(PrimitiveType.Cube);
|
||||||
var visual = GameObject.CreatePrimitive(PrimitiveType.Cube);
|
visual.transform.SetParent(prefabGO.transform, false);
|
||||||
visual.name = "Visual";
|
|
||||||
visual.transform.SetParent(prefab.transform);
|
|
||||||
visual.transform.localPosition = Vector3.zero;
|
|
||||||
visual.transform.localScale = Vector3.one * 0.3f;
|
visual.transform.localScale = Vector3.one * 0.3f;
|
||||||
DestroyImmediate(visual.GetComponent<Collider>());
|
DestroyImmediate(visual.GetComponent<Collider>());
|
||||||
}
|
}
|
||||||
|
visual.name = "Visual";
|
||||||
|
visual.transform.localPosition = Vector3.zero;
|
||||||
|
|
||||||
prefab.AddComponent<WorldItem>();
|
var worldItem = prefabGO.AddComponent<WorldItem>();
|
||||||
|
worldItem.interactRange = interactRange;
|
||||||
|
|
||||||
var col = prefab.GetComponent<Collider>();
|
var col = prefabGO.AddComponent<SphereCollider>();
|
||||||
if (col == null)
|
col.radius = 0.5f;
|
||||||
{
|
col.isTrigger = true;
|
||||||
var sphere = prefab.AddComponent<SphereCollider>();
|
|
||||||
sphere.radius = 0.5f;
|
|
||||||
sphere.isTrigger = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
GameObject savedPrefab = PrefabUtility.SaveAsPrefabAsset(prefab, path);
|
GameObject savedPrefab = PrefabUtility.SaveAsPrefabAsset(prefabGO, path);
|
||||||
DestroyImmediate(prefab);
|
DestroyImmediate(prefabGO);
|
||||||
|
|
||||||
Selection.activeObject = savedPrefab;
|
Selection.activeObject = savedPrefab;
|
||||||
Debug.Log($"[ItemBuilder] Префаб сохранён: {path}");
|
Debug.Log($"[ItemBuilder] Префаб сохранён: {path}");
|
||||||
@@ -221,9 +212,7 @@ public class ItemBuilderTool : EditorWindow
|
|||||||
var tex = new Texture2D(64, 64);
|
var tex = new Texture2D(64, 64);
|
||||||
var colors = new Color[64 * 64];
|
var colors = new Color[64 * 64];
|
||||||
for (int i = 0; i < colors.Length; i++)
|
for (int i = 0; i < colors.Length; i++)
|
||||||
{
|
|
||||||
colors[i] = previewColor;
|
colors[i] = previewColor;
|
||||||
}
|
|
||||||
tex.SetPixels(colors);
|
tex.SetPixels(colors);
|
||||||
tex.Apply();
|
tex.Apply();
|
||||||
return Sprite.Create(tex, new Rect(0, 0, 64, 64), new Vector2(0.5f, 0.5f));
|
return Sprite.Create(tex, new Rect(0, 0, 64, 64), new Vector2(0.5f, 0.5f));
|
||||||
|
|||||||
@@ -5,6 +5,10 @@ using System.Collections.Generic;
|
|||||||
using UnityEditor;
|
using UnityEditor;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Компонент для генерации ItemData ScriptableObject из настроек в Inspector.
|
||||||
|
/// Добавьте на GameObject, заполните поля и нажмите "Generate ItemData" в Inspector.
|
||||||
|
/// </summary>
|
||||||
public class ItemGenerator : MonoBehaviour
|
public class ItemGenerator : MonoBehaviour
|
||||||
{
|
{
|
||||||
[Header("Item Template")]
|
[Header("Item Template")]
|
||||||
@@ -26,9 +30,7 @@ public class ItemGenerator : MonoBehaviour
|
|||||||
public ItemData GenerateItemData()
|
public ItemData GenerateItemData()
|
||||||
{
|
{
|
||||||
if (string.IsNullOrEmpty(itemId))
|
if (string.IsNullOrEmpty(itemId))
|
||||||
{
|
|
||||||
itemId = System.Guid.NewGuid().ToString();
|
itemId = System.Guid.NewGuid().ToString();
|
||||||
}
|
|
||||||
|
|
||||||
var itemData = ScriptableObject.CreateInstance<ItemData>();
|
var itemData = ScriptableObject.CreateInstance<ItemData>();
|
||||||
itemData.id = itemId;
|
itemData.id = itemId;
|
||||||
@@ -57,187 +59,15 @@ public class ItemGenerator : MonoBehaviour
|
|||||||
public static List<ItemData> GenerateAll(List<ItemGenerator> generators)
|
public static List<ItemData> GenerateAll(List<ItemGenerator> generators)
|
||||||
{
|
{
|
||||||
var items = new List<ItemData>();
|
var items = new List<ItemData>();
|
||||||
foreach (var generator in generators)
|
foreach (var gen in generators)
|
||||||
{
|
{
|
||||||
if (generator != null)
|
if (gen != null)
|
||||||
{
|
items.Add(gen.GenerateItemData());
|
||||||
items.Add(generator.GenerateItemData());
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
return items;
|
return items;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Предмет в мире - подбирается игроком
|
|
||||||
/// </summary>
|
|
||||||
public class WorldItem : MonoBehaviour
|
|
||||||
{
|
|
||||||
public ItemData itemData;
|
|
||||||
public int amount = 1;
|
|
||||||
|
|
||||||
[Header("Settings")]
|
|
||||||
public float pickupDelay = 0f;
|
|
||||||
public bool useFactory = true;
|
|
||||||
|
|
||||||
private bool _canPickup;
|
|
||||||
|
|
||||||
public void Setup(ItemData data, int count)
|
|
||||||
{
|
|
||||||
itemData = data;
|
|
||||||
amount = count;
|
|
||||||
|
|
||||||
if (data.modelPrefab != null)
|
|
||||||
{
|
|
||||||
var model = Instantiate(data.modelPrefab, transform);
|
|
||||||
model.transform.localPosition = Vector3.zero;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Задержка перед подбором
|
|
||||||
if (pickupDelay > 0)
|
|
||||||
Invoke(nameof(EnablePickup), pickupDelay);
|
|
||||||
else
|
|
||||||
_canPickup = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
private void EnablePickup() => _canPickup = true;
|
|
||||||
|
|
||||||
void OnTriggerEnter(Collider other)
|
|
||||||
{
|
|
||||||
TryPickup(other);
|
|
||||||
}
|
|
||||||
|
|
||||||
void OnControllerColliderHit(ControllerColliderHit hit)
|
|
||||||
{
|
|
||||||
TryPickup(hit.controller);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Подобрать предмет вручную (по кнопке)
|
|
||||||
/// </summary>
|
|
||||||
public bool TryPickupByButton()
|
|
||||||
{
|
|
||||||
Debug.Log($"[TryPickup] _canPickup={_canPickup}, itemData={itemData?.itemName}, amount={amount}, Instance={InventoryManager.Instance != null}");
|
|
||||||
|
|
||||||
if (!_canPickup)
|
|
||||||
{
|
|
||||||
Debug.LogWarning("[TryPickup] Cannot pickup - not ready yet");
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
if (itemData == null)
|
|
||||||
{
|
|
||||||
Debug.LogWarning("[TryPickup] itemData is null!");
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
if (InventoryManager.Instance == null)
|
|
||||||
{
|
|
||||||
Debug.LogWarning("[TryPickup] InventoryManager.Instance is null!");
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
int remaining = InventoryManager.Instance.AddItem(itemData, amount);
|
|
||||||
Debug.Log($"[TryPickup] AddItem returned remaining={remaining}");
|
|
||||||
|
|
||||||
if (remaining <= 0)
|
|
||||||
{
|
|
||||||
Destroy(gameObject);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
amount = remaining;
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void TryPickup(Collider other)
|
|
||||||
{
|
|
||||||
if (!_canPickup) return;
|
|
||||||
if (other == null) return;
|
|
||||||
if (!other.CompareTag("Player")) return;
|
|
||||||
|
|
||||||
if (useFactory && InventoryItemFactory.Instance != null)
|
|
||||||
{
|
|
||||||
InventoryItemFactory.Instance.PickupItem(this, this);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
// Fallback - старый способ
|
|
||||||
int remaining = InventoryManager.Instance.AddItem(itemData, amount);
|
|
||||||
if (remaining <= 0)
|
|
||||||
{
|
|
||||||
Destroy(gameObject);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
amount = remaining;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Выбросить предмет с силой
|
|
||||||
/// </summary>
|
|
||||||
public void Throw(Vector3 velocity)
|
|
||||||
{
|
|
||||||
var rb = GetComponent<Rigidbody>();
|
|
||||||
if (rb == null) rb = gameObject.AddComponent<Rigidbody>();
|
|
||||||
rb.linearVelocity = velocity;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Точка спавна предмета
|
|
||||||
/// </summary>
|
|
||||||
public class ItemSpawner : MonoBehaviour
|
|
||||||
{
|
|
||||||
public ItemData item;
|
|
||||||
public int amount = 1;
|
|
||||||
public float despawnTime = 300f;
|
|
||||||
public bool spawnOnStart = false;
|
|
||||||
public bool useFactory = true;
|
|
||||||
|
|
||||||
public void Setup(ItemData itemData, int itemAmount, float despawn)
|
|
||||||
{
|
|
||||||
item = itemData;
|
|
||||||
amount = itemAmount;
|
|
||||||
despawnTime = despawn;
|
|
||||||
}
|
|
||||||
|
|
||||||
void Start()
|
|
||||||
{
|
|
||||||
if (spawnOnStart) Spawn();
|
|
||||||
}
|
|
||||||
|
|
||||||
public void Spawn()
|
|
||||||
{
|
|
||||||
if (useFactory && InventoryItemFactory.Instance != null)
|
|
||||||
{
|
|
||||||
var worldItem = InventoryItemFactory.Instance.CreateWorldItem(item, amount, transform.position);
|
|
||||||
if (worldItem != null && despawnTime > 0)
|
|
||||||
{
|
|
||||||
Destroy(worldItem.gameObject, despawnTime);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
// Fallback - старый способ
|
|
||||||
var prefab = Resources.Load<GameObject>("Prefabs/WorldItem");
|
|
||||||
if (prefab != null)
|
|
||||||
{
|
|
||||||
var worldItem = Instantiate(prefab, transform.position, Quaternion.identity).GetComponent<WorldItem>();
|
|
||||||
worldItem.Setup(item, amount);
|
|
||||||
Destroy(worldItem.gameObject, despawnTime);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public void Despawn()
|
|
||||||
{
|
|
||||||
Destroy(gameObject);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#if UNITY_EDITOR
|
#if UNITY_EDITOR
|
||||||
[CustomEditor(typeof(ItemGenerator))]
|
[CustomEditor(typeof(ItemGenerator))]
|
||||||
public class ItemGeneratorEditor : Editor
|
public class ItemGeneratorEditor : Editor
|
||||||
@@ -246,16 +76,22 @@ public class ItemGeneratorEditor : Editor
|
|||||||
{
|
{
|
||||||
base.OnInspectorGUI();
|
base.OnInspectorGUI();
|
||||||
|
|
||||||
|
GUILayout.Space(8);
|
||||||
|
|
||||||
if (GUILayout.Button("Generate ItemData"))
|
if (GUILayout.Button("Generate ItemData"))
|
||||||
{
|
{
|
||||||
var generator = (ItemGenerator)target;
|
var generator = (ItemGenerator)target;
|
||||||
var itemData = generator.GenerateItemData();
|
var itemData = generator.GenerateItemData();
|
||||||
|
|
||||||
string path = $"Assets/Inventory/Items/{itemData.itemName}.asset";
|
string folder = "Assets/Inventory/Items";
|
||||||
|
if (!System.IO.Directory.Exists(folder))
|
||||||
|
System.IO.Directory.CreateDirectory(folder);
|
||||||
|
|
||||||
|
string path = $"{folder}/{itemData.itemName}.asset";
|
||||||
AssetDatabase.CreateAsset(itemData, path);
|
AssetDatabase.CreateAsset(itemData, path);
|
||||||
AssetDatabase.SaveAssets();
|
AssetDatabase.SaveAssets();
|
||||||
|
|
||||||
Debug.Log($"Created item: {itemData.itemName} at {path}");
|
Debug.Log($"[ItemGenerator] Created item: {itemData.itemName} at {path}");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
39
Assets/Inventory/Scripts/ItemSpawner.cs
Normal file
39
Assets/Inventory/Scripts/ItemSpawner.cs
Normal file
@@ -0,0 +1,39 @@
|
|||||||
|
using UnityEngine;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Точка спавна предмета в мире. Создаёт WorldItem при старте или по вызову Spawn().
|
||||||
|
/// </summary>
|
||||||
|
public class ItemSpawner : MonoBehaviour
|
||||||
|
{
|
||||||
|
public ItemData item;
|
||||||
|
public int amount = 1;
|
||||||
|
public float despawnTime = 300f;
|
||||||
|
public bool spawnOnStart = false;
|
||||||
|
|
||||||
|
public void Setup(ItemData itemData, int itemAmount, float despawn)
|
||||||
|
{
|
||||||
|
item = itemData;
|
||||||
|
amount = itemAmount;
|
||||||
|
despawnTime = despawn;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Start()
|
||||||
|
{
|
||||||
|
if (spawnOnStart) Spawn();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Spawn()
|
||||||
|
{
|
||||||
|
if (InventoryItemFactory.Instance != null)
|
||||||
|
{
|
||||||
|
var worldItem = InventoryItemFactory.Instance.CreateWorldItem(item, amount, transform.position);
|
||||||
|
if (worldItem != null && despawnTime > 0)
|
||||||
|
Destroy(worldItem.gameObject, despawnTime);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Despawn()
|
||||||
|
{
|
||||||
|
Destroy(gameObject);
|
||||||
|
}
|
||||||
|
}
|
||||||
2
Assets/Inventory/Scripts/ItemSpawner.cs.meta
Normal file
2
Assets/Inventory/Scripts/ItemSpawner.cs.meta
Normal file
@@ -0,0 +1,2 @@
|
|||||||
|
fileFormatVersion: 2
|
||||||
|
guid: 42e70e59bb536584aa49153a0f13c202
|
||||||
78
Assets/Inventory/Scripts/WorldItem.cs
Normal file
78
Assets/Inventory/Scripts/WorldItem.cs
Normal file
@@ -0,0 +1,78 @@
|
|||||||
|
using UnityEngine;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Предмет в мире — подбирается только по нажатию кнопки E (через charecter.cs).
|
||||||
|
/// Авто-подбор при касании намеренно убран.
|
||||||
|
/// </summary>
|
||||||
|
public class WorldItem : MonoBehaviour
|
||||||
|
{
|
||||||
|
public ItemData itemData;
|
||||||
|
public int amount = 1;
|
||||||
|
|
||||||
|
[Header("Pickup")]
|
||||||
|
public float pickupDelay = 0f;
|
||||||
|
public float interactRange = 2.5f;
|
||||||
|
|
||||||
|
private bool _canPickup;
|
||||||
|
|
||||||
|
public void Setup(ItemData data, int count)
|
||||||
|
{
|
||||||
|
itemData = data;
|
||||||
|
amount = count;
|
||||||
|
|
||||||
|
if (data.modelPrefab != null)
|
||||||
|
{
|
||||||
|
var model = Instantiate(data.modelPrefab, transform);
|
||||||
|
model.transform.localPosition = Vector3.zero;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (pickupDelay > 0)
|
||||||
|
Invoke(nameof(EnablePickup), pickupDelay);
|
||||||
|
else
|
||||||
|
_canPickup = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void EnablePickup() => _canPickup = true;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Вызывается из charecter.cs при нажатии E рядом с предметом.
|
||||||
|
/// </summary>
|
||||||
|
public bool TryPickupByButton()
|
||||||
|
{
|
||||||
|
if (!_canPickup)
|
||||||
|
{
|
||||||
|
Debug.LogWarning("[WorldItem] Cannot pickup — delay not elapsed yet");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (itemData == null)
|
||||||
|
{
|
||||||
|
Debug.LogWarning("[WorldItem] itemData is null!");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (InventoryManager.Instance == null)
|
||||||
|
{
|
||||||
|
Debug.LogWarning("[WorldItem] InventoryManager.Instance is null!");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
int remaining = InventoryManager.Instance.AddItem(itemData, amount);
|
||||||
|
if (remaining <= 0)
|
||||||
|
{
|
||||||
|
Destroy(gameObject);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
amount = remaining;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Выбросить предмет с физической силой.
|
||||||
|
/// </summary>
|
||||||
|
public void Throw(Vector3 velocity)
|
||||||
|
{
|
||||||
|
var rb = GetComponent<Rigidbody>();
|
||||||
|
if (rb == null) rb = gameObject.AddComponent<Rigidbody>();
|
||||||
|
rb.linearVelocity = velocity;
|
||||||
|
}
|
||||||
|
}
|
||||||
2
Assets/Inventory/Scripts/WorldItem.cs.meta
Normal file
2
Assets/Inventory/Scripts/WorldItem.cs.meta
Normal file
@@ -0,0 +1,2 @@
|
|||||||
|
fileFormatVersion: 2
|
||||||
|
guid: b8ac54fbf9ed99e45a83319443952a91
|
||||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because one or more lines are too long
106
Assets/charecter-controller/scripts/HandEquipSystem.cs
Normal file
106
Assets/charecter-controller/scripts/HandEquipSystem.cs
Normal file
@@ -0,0 +1,106 @@
|
|||||||
|
using UnityEngine;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Показывает модель активного предмета хотбара в руке персонажа.
|
||||||
|
/// Принцип — как в Minecraft: выбранный слот хотбара = предмет в правой руке.
|
||||||
|
/// Добавьте на Player, назначьте handBone в Inspector.
|
||||||
|
/// </summary>
|
||||||
|
public class HandEquipSystem : MonoBehaviour
|
||||||
|
{
|
||||||
|
[Header("Hand Setup")]
|
||||||
|
[Tooltip("Кость правой руки из скелета персонажа")]
|
||||||
|
public Transform handBone;
|
||||||
|
|
||||||
|
[Tooltip("Смещение предмета относительно кости руки")]
|
||||||
|
public Vector3 itemOffset = Vector3.zero;
|
||||||
|
|
||||||
|
[Tooltip("Поворот предмета в руке (euler)")]
|
||||||
|
public Vector3 itemRotation = Vector3.zero;
|
||||||
|
|
||||||
|
[Tooltip("Масштаб предмета в руке")]
|
||||||
|
public Vector3 itemScale = Vector3.one;
|
||||||
|
|
||||||
|
// ── Приватные поля ────────────────────────────────────────────────────────
|
||||||
|
private GameObject _currentHandItem;
|
||||||
|
|
||||||
|
// ── Lifecycle ─────────────────────────────────────────────────────────────
|
||||||
|
void Start()
|
||||||
|
{
|
||||||
|
// Подписываемся на смену слота хотбара
|
||||||
|
if (PlayerInput.Instance != null)
|
||||||
|
PlayerInput.Instance.OnHotbarSelect += OnHotbarSlotSelected;
|
||||||
|
|
||||||
|
// Подписываемся на изменение слотов (drag-drop, добавление/удаление)
|
||||||
|
if (InventoryEvents.Instance != null)
|
||||||
|
InventoryEvents.Instance.OnSlotChanged.AddListener(OnSlotChanged);
|
||||||
|
|
||||||
|
UpdateHandItem();
|
||||||
|
}
|
||||||
|
|
||||||
|
void OnDestroy()
|
||||||
|
{
|
||||||
|
if (PlayerInput.Instance != null)
|
||||||
|
PlayerInput.Instance.OnHotbarSelect -= OnHotbarSlotSelected;
|
||||||
|
|
||||||
|
if (InventoryEvents.Instance != null)
|
||||||
|
InventoryEvents.Instance.OnSlotChanged.RemoveListener(OnSlotChanged);
|
||||||
|
}
|
||||||
|
|
||||||
|
// ── Обработчики событий ───────────────────────────────────────────────────
|
||||||
|
|
||||||
|
private void OnHotbarSlotSelected(int index) => UpdateHandItem();
|
||||||
|
|
||||||
|
private void OnSlotChanged(int slotIndex, string itemId) => UpdateHandItem();
|
||||||
|
|
||||||
|
// ── Логика обновления предмета в руке ────────────────────────────────────
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Обновить объект в руке под текущий выбранный слот хотбара.
|
||||||
|
/// Можно вызвать вручную если нужно принудительное обновление.
|
||||||
|
/// </summary>
|
||||||
|
public void UpdateHandItem()
|
||||||
|
{
|
||||||
|
// Уничтожить старый объект в руке
|
||||||
|
if (_currentHandItem != null)
|
||||||
|
{
|
||||||
|
Destroy(_currentHandItem);
|
||||||
|
_currentHandItem = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (handBone == null)
|
||||||
|
{
|
||||||
|
Debug.LogWarning("[HandEquipSystem] handBone не назначен!");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (InventoryManager.Instance == null) return;
|
||||||
|
|
||||||
|
var item = InventoryManager.Instance.GetSelectedHotbarItem();
|
||||||
|
if (item == null || item.modelPrefab == null) return;
|
||||||
|
|
||||||
|
// Создать модель как дочерний объект кости руки
|
||||||
|
_currentHandItem = Instantiate(item.modelPrefab, handBone);
|
||||||
|
_currentHandItem.name = $"HandItem_{item.itemName}";
|
||||||
|
_currentHandItem.transform.localPosition = itemOffset;
|
||||||
|
_currentHandItem.transform.localEulerAngles = itemRotation;
|
||||||
|
_currentHandItem.transform.localScale = itemScale;
|
||||||
|
|
||||||
|
// Отключить физику и коллайдеры — предмет в руке не должен взаимодействовать с миром
|
||||||
|
foreach (var col in _currentHandItem.GetComponentsInChildren<Collider>())
|
||||||
|
col.enabled = false;
|
||||||
|
foreach (var rb in _currentHandItem.GetComponentsInChildren<Rigidbody>())
|
||||||
|
rb.isKinematic = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Убрать предмет из руки (например когда открыт инвентарь).
|
||||||
|
/// </summary>
|
||||||
|
public void ClearHandItem()
|
||||||
|
{
|
||||||
|
if (_currentHandItem != null)
|
||||||
|
{
|
||||||
|
Destroy(_currentHandItem);
|
||||||
|
_currentHandItem = null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,2 @@
|
|||||||
|
fileFormatVersion: 2
|
||||||
|
guid: a73f597bcce79104fb38225b98ff9348
|
||||||
@@ -1,185 +0,0 @@
|
|||||||
using UnityEngine;
|
|
||||||
|
|
||||||
#if UNITY_EDITOR
|
|
||||||
using UnityEditor;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
public class PlayerBuilder : MonoBehaviour
|
|
||||||
{
|
|
||||||
[Header("Character Model")]
|
|
||||||
public GameObject characterModel;
|
|
||||||
public Transform headBone;
|
|
||||||
|
|
||||||
[Header("Movement Settings")]
|
|
||||||
public float walkSpeed = 5f;
|
|
||||||
public float runSpeed = 9f;
|
|
||||||
public float crouchSpeed = 2.5f;
|
|
||||||
public float jumpHeight = 1.5f;
|
|
||||||
public float gravity = -9.81f;
|
|
||||||
|
|
||||||
[Header("Camera")]
|
|
||||||
public bool addCamera = true;
|
|
||||||
|
|
||||||
[Header("Collider")]
|
|
||||||
public float height = 1.8f;
|
|
||||||
public float radius = 0.5f;
|
|
||||||
public Vector3 center = new Vector3(0, 0.9f, 0);
|
|
||||||
|
|
||||||
public GameObject BuildPlayer(string playerName = "Player")
|
|
||||||
{
|
|
||||||
GameObject player = new GameObject(playerName);
|
|
||||||
|
|
||||||
var cc = player.AddComponent<CharacterController>();
|
|
||||||
cc.height = height;
|
|
||||||
cc.radius = radius;
|
|
||||||
cc.center = center;
|
|
||||||
|
|
||||||
var character = player.AddComponent<charecter>();
|
|
||||||
character.walkSpeed = walkSpeed;
|
|
||||||
character.runSpeed = runSpeed;
|
|
||||||
character.crouchSpeed = crouchSpeed;
|
|
||||||
character.jumpHeight = jumpHeight;
|
|
||||||
character.gravity = gravity;
|
|
||||||
|
|
||||||
GameObject model = null;
|
|
||||||
if (characterModel != null)
|
|
||||||
{
|
|
||||||
model = Instantiate(characterModel, player.transform);
|
|
||||||
model.transform.localPosition = Vector3.zero;
|
|
||||||
model.transform.localRotation = Quaternion.identity;
|
|
||||||
|
|
||||||
if (headBone != null)
|
|
||||||
{
|
|
||||||
character.head = headBone;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
character.head = FindChildBone(model.transform, "Head");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (character.head == null)
|
|
||||||
{
|
|
||||||
GameObject headObj = new GameObject("HeadPoint");
|
|
||||||
headObj.transform.SetParent(model != null ? model.transform : player.transform);
|
|
||||||
headObj.transform.localPosition = new Vector3(0, 1.6f, 0);
|
|
||||||
character.head = headObj.transform;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (addCamera && character.head != null)
|
|
||||||
{
|
|
||||||
GameObject cameraObj = new GameObject("PlayerCamera");
|
|
||||||
cameraObj.transform.SetParent(character.head);
|
|
||||||
cameraObj.transform.localPosition = new Vector3(0, 0.1f, 0);
|
|
||||||
|
|
||||||
var camera = cameraObj.AddComponent<Camera>();
|
|
||||||
camera.tag = "MainCamera";
|
|
||||||
|
|
||||||
var oldCamera = GameObject.FindWithTag("MainCamera");
|
|
||||||
if (oldCamera != null && oldCamera != cameraObj)
|
|
||||||
{
|
|
||||||
oldCamera.tag = "Untagged";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
player.tag = "Player";
|
|
||||||
|
|
||||||
var rb = player.AddComponent<Rigidbody>();
|
|
||||||
rb.useGravity = false;
|
|
||||||
rb.isKinematic = true;
|
|
||||||
rb.constraints = RigidbodyConstraints.FreezeRotation;
|
|
||||||
|
|
||||||
return player;
|
|
||||||
}
|
|
||||||
|
|
||||||
public Transform FindChildBone(Transform parent, string boneName)
|
|
||||||
{
|
|
||||||
if (parent == null) return null;
|
|
||||||
|
|
||||||
if (parent.name.ToLower().Contains(boneName.ToLower()))
|
|
||||||
return parent;
|
|
||||||
|
|
||||||
foreach (Transform child in parent)
|
|
||||||
{
|
|
||||||
var result = FindChildBone(child, boneName);
|
|
||||||
if (result != null) return result;
|
|
||||||
}
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#if UNITY_EDITOR
|
|
||||||
[CustomEditor(typeof(PlayerBuilder))]
|
|
||||||
public class PlayerBuilderEditor : Editor
|
|
||||||
{
|
|
||||||
public override void OnInspectorGUI()
|
|
||||||
{
|
|
||||||
base.OnInspectorGUI();
|
|
||||||
|
|
||||||
var builder = (PlayerBuilder)target;
|
|
||||||
|
|
||||||
GUILayout.Space(15);
|
|
||||||
|
|
||||||
if (GUILayout.Button("Создать игрока в сцене"))
|
|
||||||
{
|
|
||||||
builder.BuildPlayer();
|
|
||||||
}
|
|
||||||
|
|
||||||
GUILayout.Space(10);
|
|
||||||
EditorGUILayout.HelpBox(
|
|
||||||
"1. Назначьте модель персонажа\n" +
|
|
||||||
"2. Настройте параметры движения\n" +
|
|
||||||
"3. Нажмите 'Создать игрока'",
|
|
||||||
MessageType.Info);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public static class PlayerBuilderMenu
|
|
||||||
{
|
|
||||||
[MenuItem("GameObject/Create Player/Quick Test Player", false, 0)]
|
|
||||||
public static void CreateQuickTestPlayer()
|
|
||||||
{
|
|
||||||
var go = new GameObject("TestPlayer");
|
|
||||||
|
|
||||||
var cc = go.AddComponent<CharacterController>();
|
|
||||||
cc.height = 1.8f;
|
|
||||||
cc.radius = 0.5f;
|
|
||||||
cc.center = new Vector3(0, 0.9f, 0);
|
|
||||||
|
|
||||||
var character = go.AddComponent<charecter>();
|
|
||||||
character.walkSpeed = 5f;
|
|
||||||
character.runSpeed = 9f;
|
|
||||||
character.crouchSpeed = 2.5f;
|
|
||||||
character.jumpHeight = 1.5f;
|
|
||||||
character.gravity = -9.81f;
|
|
||||||
|
|
||||||
GameObject body = GameObject.CreatePrimitive(PrimitiveType.Capsule);
|
|
||||||
body.name = "Body";
|
|
||||||
body.transform.SetParent(go.transform);
|
|
||||||
body.transform.localPosition = Vector3.zero;
|
|
||||||
GameObject.Destroy(body.GetComponent<Collider>());
|
|
||||||
|
|
||||||
GameObject head = new GameObject("Head");
|
|
||||||
head.transform.SetParent(go.transform);
|
|
||||||
head.transform.localPosition = new Vector3(0, 0.8f, 0);
|
|
||||||
character.head = head.transform;
|
|
||||||
|
|
||||||
GameObject camObj = new GameObject("PlayerCamera");
|
|
||||||
camObj.transform.SetParent(head.transform);
|
|
||||||
camObj.transform.localPosition = new Vector3(0, 0.1f, 0);
|
|
||||||
var cam = camObj.AddComponent<Camera>();
|
|
||||||
cam.tag = "MainCamera";
|
|
||||||
|
|
||||||
var existingCam = GameObject.FindGameObjectWithTag("MainCamera");
|
|
||||||
if (existingCam != null && existingCam != camObj)
|
|
||||||
{
|
|
||||||
GameObject.Destroy(existingCam);
|
|
||||||
}
|
|
||||||
|
|
||||||
go.tag = "Player";
|
|
||||||
go.transform.position = new Vector3(0, 2, -5);
|
|
||||||
|
|
||||||
Selection.activeGameObject = go;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
@@ -1,2 +0,0 @@
|
|||||||
fileFormatVersion: 2
|
|
||||||
guid: 47acf8134d655aa4da32eb965ee9590e
|
|
||||||
@@ -1,31 +1,45 @@
|
|||||||
using UnityEngine;
|
using UnityEngine;
|
||||||
using UnityEngine.UI;
|
|
||||||
using UnityEditor;
|
using UnityEditor;
|
||||||
using UnityEditor.Animations;
|
using UnityEditor.Animations;
|
||||||
|
using UnityEngine.UI;
|
||||||
|
using UnityEngine.EventSystems;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Инструмент создания полного игрока с опциональным инвентарём.
|
||||||
|
/// Tools > Player Builder
|
||||||
|
/// </summary>
|
||||||
public class PlayerBuilderTool : EditorWindow
|
public class PlayerBuilderTool : EditorWindow
|
||||||
{
|
{
|
||||||
// Модель
|
// ── Модель ────────────────────────────────────────────────────────────────
|
||||||
private GameObject characterModel;
|
private GameObject characterModel;
|
||||||
private Transform headBone;
|
private Transform headBone;
|
||||||
|
private Transform handBone;
|
||||||
|
|
||||||
// Параметры движения
|
// ── Параметры движения ────────────────────────────────────────────────────
|
||||||
private float walkSpeed = 5f;
|
private float walkSpeed = 5f;
|
||||||
private float runSpeed = 9f;
|
private float runSpeed = 9f;
|
||||||
private float crouchSpeed = 2.5f;
|
private float crouchSpeed = 2.5f;
|
||||||
private float jumpHeight = 1.5f;
|
private float jumpHeight = 1.5f;
|
||||||
private float gravity = -9.81f;
|
private float gravity = -9.81f;
|
||||||
|
|
||||||
// Коллайдер
|
// ── Коллайдер ─────────────────────────────────────────────────────────────
|
||||||
private float height = 1.8f;
|
private float height = 1.8f;
|
||||||
private float radius = 0.5f;
|
private float radius = 0.5f;
|
||||||
private float centerY = 0.9f;
|
private float centerY = 0.9f;
|
||||||
|
|
||||||
// Камера
|
// ── Камера ────────────────────────────────────────────────────────────────
|
||||||
private bool addCamera = true;
|
private bool addCamera = true;
|
||||||
private float cameraHeight = 1.7f;
|
private float cameraHeight = 1.7f;
|
||||||
|
|
||||||
// Анимации
|
// ── Инвентарь ─────────────────────────────────────────────────────────────
|
||||||
|
private bool includeInventory = true;
|
||||||
|
private int inventorySlots = 36;
|
||||||
|
private int hotbarSlots = 9;
|
||||||
|
|
||||||
|
// ── Input Actions ─────────────────────────────────────────────────────────
|
||||||
|
private UnityEngine.InputSystem.InputActionAsset inputActions;
|
||||||
|
|
||||||
|
// ── Анимации ──────────────────────────────────────────────────────────────
|
||||||
private AnimationClip idleClip;
|
private AnimationClip idleClip;
|
||||||
private AnimationClip walkClip;
|
private AnimationClip walkClip;
|
||||||
private AnimationClip runClip;
|
private AnimationClip runClip;
|
||||||
@@ -33,9 +47,8 @@ public class PlayerBuilderTool : EditorWindow
|
|||||||
private AnimationClip crouchIdleClip;
|
private AnimationClip crouchIdleClip;
|
||||||
private AnimationClip crouchWalkClip;
|
private AnimationClip crouchWalkClip;
|
||||||
|
|
||||||
// Аниматор контроллер
|
// ── Scroll ────────────────────────────────────────────────────────────────
|
||||||
private AnimatorController animatorController;
|
private Vector2 _scroll;
|
||||||
private bool createAnimatorController = true;
|
|
||||||
|
|
||||||
[MenuItem("Tools/Player Builder")]
|
[MenuItem("Tools/Player Builder")]
|
||||||
public static void ShowWindow()
|
public static void ShowWindow()
|
||||||
@@ -45,46 +58,67 @@ public class PlayerBuilderTool : EditorWindow
|
|||||||
|
|
||||||
void OnGUI()
|
void OnGUI()
|
||||||
{
|
{
|
||||||
GUILayout.Label("Настройки персонажа", EditorStyles.boldLabel);
|
_scroll = EditorGUILayout.BeginScrollView(_scroll);
|
||||||
|
|
||||||
// Секция модели
|
GUILayout.Label("Конструктор Персонажа", EditorStyles.boldLabel);
|
||||||
|
|
||||||
|
// ── Секция модели ─────────────────────────────────────────────────────
|
||||||
|
GUILayout.Space(6);
|
||||||
GUILayout.Label("Модель", EditorStyles.miniBoldLabel);
|
GUILayout.Label("Модель", EditorStyles.miniBoldLabel);
|
||||||
characterModel = (GameObject)EditorGUILayout.ObjectField("Модель персонажа", characterModel, typeof(GameObject), false);
|
characterModel = (GameObject)EditorGUILayout.ObjectField("Модель персонажа", characterModel, typeof(GameObject), false);
|
||||||
headBone = (Transform)EditorGUILayout.ObjectField("Кость головы", headBone, typeof(Transform), true);
|
headBone = (Transform)EditorGUILayout.ObjectField("Кость головы (Head)", headBone, typeof(Transform), true);
|
||||||
|
handBone = (Transform)EditorGUILayout.ObjectField("Кость руки (RightHand)", handBone, typeof(Transform), true);
|
||||||
|
|
||||||
GUILayout.Space(10);
|
if (characterModel != null && GUILayout.Button("Автопоиск костей Head/Hand"))
|
||||||
|
AutoFindBones();
|
||||||
|
|
||||||
// Секция движения
|
// ── Движение ──────────────────────────────────────────────────────────
|
||||||
|
GUILayout.Space(6);
|
||||||
GUILayout.Label("Движение", EditorStyles.miniBoldLabel);
|
GUILayout.Label("Движение", EditorStyles.miniBoldLabel);
|
||||||
walkSpeed = EditorGUILayout.FloatField("Скорость ходьбы", walkSpeed);
|
walkSpeed = EditorGUILayout.FloatField("Скорость ходьбы", walkSpeed);
|
||||||
runSpeed = EditorGUILayout.FloatField("Скорость бега", runSpeed);
|
runSpeed = EditorGUILayout.FloatField("Скорость бега", runSpeed);
|
||||||
crouchSpeed = EditorGUILayout.FloatField("Скорость краулинга", crouchSpeed);
|
crouchSpeed = EditorGUILayout.FloatField("Скорость присядки", crouchSpeed);
|
||||||
jumpHeight = EditorGUILayout.FloatField("Высота прыжка", jumpHeight);
|
jumpHeight = EditorGUILayout.FloatField("Высота прыжка", jumpHeight);
|
||||||
gravity = EditorGUILayout.FloatField("Гравитация", gravity);
|
gravity = EditorGUILayout.FloatField("Гравитация", gravity);
|
||||||
|
|
||||||
GUILayout.Space(10);
|
// ── Коллайдер ─────────────────────────────────────────────────────────
|
||||||
|
GUILayout.Space(6);
|
||||||
// Секция коллайдера
|
GUILayout.Label("Коллайдер CharacterController", EditorStyles.miniBoldLabel);
|
||||||
GUILayout.Label("Коллайдер", EditorStyles.miniBoldLabel);
|
|
||||||
height = EditorGUILayout.FloatField("Высота", height);
|
height = EditorGUILayout.FloatField("Высота", height);
|
||||||
radius = EditorGUILayout.FloatField("Радиус", radius);
|
radius = EditorGUILayout.FloatField("Радиус", radius);
|
||||||
centerY = EditorGUILayout.FloatField("Центр Y", centerY);
|
centerY = EditorGUILayout.FloatField("Центр Y", centerY);
|
||||||
|
|
||||||
GUILayout.Space(10);
|
// ── Камера ────────────────────────────────────────────────────────────
|
||||||
|
GUILayout.Space(6);
|
||||||
// Секция камеры
|
|
||||||
GUILayout.Label("Камера", EditorStyles.miniBoldLabel);
|
GUILayout.Label("Камера", EditorStyles.miniBoldLabel);
|
||||||
addCamera = EditorGUILayout.Toggle("Добавить камеру", addCamera);
|
addCamera = EditorGUILayout.Toggle("Добавить камеру", addCamera);
|
||||||
if (addCamera)
|
if (addCamera)
|
||||||
{
|
|
||||||
cameraHeight = EditorGUILayout.Slider("Высота камеры", cameraHeight, 1f, 2f);
|
cameraHeight = EditorGUILayout.Slider("Высота камеры", cameraHeight, 1f, 2f);
|
||||||
|
|
||||||
|
// ── Input Actions ─────────────────────────────────────────────────────
|
||||||
|
GUILayout.Space(6);
|
||||||
|
GUILayout.Label("Input System", EditorStyles.miniBoldLabel);
|
||||||
|
inputActions = (UnityEngine.InputSystem.InputActionAsset)EditorGUILayout.ObjectField(
|
||||||
|
"PlayerControls.inputactions",
|
||||||
|
inputActions,
|
||||||
|
typeof(UnityEngine.InputSystem.InputActionAsset),
|
||||||
|
false);
|
||||||
|
if (inputActions == null)
|
||||||
|
EditorGUILayout.HelpBox("Назначьте Assets/Input/PlayerControls.inputactions", MessageType.Warning);
|
||||||
|
|
||||||
|
// ── Инвентарь ─────────────────────────────────────────────────────────
|
||||||
|
GUILayout.Space(6);
|
||||||
|
GUILayout.Label("Инвентарь", EditorStyles.miniBoldLabel);
|
||||||
|
includeInventory = EditorGUILayout.Toggle("Включить инвентарь", includeInventory);
|
||||||
|
if (includeInventory)
|
||||||
|
{
|
||||||
|
inventorySlots = EditorGUILayout.IntField("Слотов инвентаря", inventorySlots);
|
||||||
|
hotbarSlots = EditorGUILayout.IntField("Слотов хотбара", hotbarSlots);
|
||||||
}
|
}
|
||||||
|
|
||||||
GUILayout.Space(10);
|
// ── Анимации ──────────────────────────────────────────────────────────
|
||||||
|
GUILayout.Space(6);
|
||||||
// Секция анимаций
|
GUILayout.Label("Анимации (опционально)", EditorStyles.miniBoldLabel);
|
||||||
GUILayout.Label("Анимации", EditorStyles.miniBoldLabel);
|
|
||||||
createAnimatorController = EditorGUILayout.Toggle("Создать контроллер", createAnimatorController);
|
|
||||||
idleClip = (AnimationClip)EditorGUILayout.ObjectField("Idle", idleClip, typeof(AnimationClip), false);
|
idleClip = (AnimationClip)EditorGUILayout.ObjectField("Idle", idleClip, typeof(AnimationClip), false);
|
||||||
walkClip = (AnimationClip)EditorGUILayout.ObjectField("Walk", walkClip, typeof(AnimationClip), false);
|
walkClip = (AnimationClip)EditorGUILayout.ObjectField("Walk", walkClip, typeof(AnimationClip), false);
|
||||||
runClip = (AnimationClip)EditorGUILayout.ObjectField("Run", runClip, typeof(AnimationClip), false);
|
runClip = (AnimationClip)EditorGUILayout.ObjectField("Run", runClip, typeof(AnimationClip), false);
|
||||||
@@ -92,50 +126,53 @@ public class PlayerBuilderTool : EditorWindow
|
|||||||
crouchIdleClip = (AnimationClip)EditorGUILayout.ObjectField("Crouch Idle", crouchIdleClip, typeof(AnimationClip), false);
|
crouchIdleClip = (AnimationClip)EditorGUILayout.ObjectField("Crouch Idle", crouchIdleClip, typeof(AnimationClip), false);
|
||||||
crouchWalkClip = (AnimationClip)EditorGUILayout.ObjectField("Crouch Walk", crouchWalkClip, typeof(AnimationClip), false);
|
crouchWalkClip = (AnimationClip)EditorGUILayout.ObjectField("Crouch Walk", crouchWalkClip, typeof(AnimationClip), false);
|
||||||
|
|
||||||
if (characterModel != null)
|
|
||||||
{
|
|
||||||
var animator = characterModel.GetComponent<Animator>();
|
|
||||||
if (animator != null && animator.avatar != null)
|
|
||||||
{
|
|
||||||
EditorGUILayout.HelpBox("Модель содержит Animator - аватар будет скопирован", MessageType.Info);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
GUILayout.Space(20);
|
GUILayout.Space(20);
|
||||||
|
|
||||||
// Кнопки действий
|
// ── Кнопки ────────────────────────────────────────────────────────────
|
||||||
GUI.color = Color.green;
|
GUI.color = Color.green;
|
||||||
if (GUILayout.Button("Создать в сцене"))
|
if (GUILayout.Button("Создать игрока" + (includeInventory ? " + Инвентарь" : "")))
|
||||||
{
|
|
||||||
BuildPlayer("Player");
|
BuildPlayer("Player");
|
||||||
}
|
|
||||||
|
GUI.color = Color.yellow;
|
||||||
|
if (GUILayout.Button("Создать тестового игрока (капсула)"))
|
||||||
|
BuildTestPlayer();
|
||||||
|
|
||||||
GUI.color = Color.cyan;
|
GUI.color = Color.cyan;
|
||||||
if (GUILayout.Button("Сохранить как префаб"))
|
if (GUILayout.Button("Сохранить как префаб"))
|
||||||
{
|
|
||||||
SaveAsPrefab();
|
SaveAsPrefab();
|
||||||
}
|
|
||||||
|
|
||||||
GUI.color = Color.yellow;
|
|
||||||
if (GUILayout.Button("Создать с тестовой моделью (капсула)"))
|
|
||||||
{
|
|
||||||
BuildTestPlayer();
|
|
||||||
}
|
|
||||||
|
|
||||||
GUI.color = Color.white;
|
GUI.color = Color.white;
|
||||||
|
|
||||||
GUILayout.Space(10);
|
GUILayout.Space(10);
|
||||||
EditorGUILayout.HelpBox(
|
EditorGUILayout.HelpBox(
|
||||||
"1. Назначьте модель персонажа\n" +
|
"1. Назначьте модель персонажа (опционально)\n" +
|
||||||
"2. Назначьте анимации (опционально)\n" +
|
"2. Укажите кость головы и кость руки\n" +
|
||||||
"3. Настройте параметры\n" +
|
"3. Назначьте PlayerControls.inputactions\n" +
|
||||||
"4. Нажмите 'Создать в сцене'",
|
"4. Нажмите 'Создать игрока'",
|
||||||
MessageType.Info);
|
MessageType.Info);
|
||||||
|
|
||||||
|
EditorGUILayout.EndScrollView();
|
||||||
}
|
}
|
||||||
|
|
||||||
void BuildPlayer(string playerName)
|
// ── Автопоиск костей ─────────────────────────────────────────────────────
|
||||||
|
|
||||||
|
void AutoFindBones()
|
||||||
{
|
{
|
||||||
GameObject player = new GameObject(playerName);
|
if (characterModel == null) return;
|
||||||
|
headBone = FindChildBone(characterModel.transform, "head") ??
|
||||||
|
FindChildBone(characterModel.transform, "Head");
|
||||||
|
handBone = FindChildBone(characterModel.transform, "hand_r") ??
|
||||||
|
FindChildBone(characterModel.transform, "RightHand") ??
|
||||||
|
FindChildBone(characterModel.transform, "Hand_R") ??
|
||||||
|
FindChildBone(characterModel.transform, "hand");
|
||||||
|
Debug.Log($"[PlayerBuilder] Head: {headBone?.name ?? "не найдена"}, Hand: {handBone?.name ?? "не найдена"}");
|
||||||
|
}
|
||||||
|
|
||||||
|
// ── Создание игрока ───────────────────────────────────────────────────────
|
||||||
|
|
||||||
|
GameObject BuildPlayerGO(string playerName)
|
||||||
|
{
|
||||||
|
var player = new GameObject(playerName);
|
||||||
|
|
||||||
// CharacterController
|
// CharacterController
|
||||||
var cc = player.AddComponent<CharacterController>();
|
var cc = player.AddComponent<CharacterController>();
|
||||||
@@ -152,24 +189,20 @@ public class PlayerBuilderTool : EditorWindow
|
|||||||
character.gravity = gravity;
|
character.gravity = gravity;
|
||||||
|
|
||||||
// Модель
|
// Модель
|
||||||
GameObject model = null;
|
Transform resolvedHead = headBone;
|
||||||
|
Transform resolvedHand = handBone;
|
||||||
|
|
||||||
if (characterModel != null)
|
if (characterModel != null)
|
||||||
{
|
{
|
||||||
model = Instantiate(characterModel, player.transform);
|
var model = (GameObject)PrefabUtility.InstantiatePrefab(characterModel, player.transform);
|
||||||
model.transform.localPosition = Vector3.zero;
|
model.transform.localPosition = Vector3.zero;
|
||||||
model.transform.localRotation = Quaternion.identity;
|
model.transform.localRotation = Quaternion.identity;
|
||||||
|
|
||||||
// Голова
|
if (resolvedHead == null)
|
||||||
if (headBone != null)
|
resolvedHead = FindChildBone(model.transform, "head") ?? FindChildBone(model.transform, "Head");
|
||||||
{
|
if (resolvedHand == null)
|
||||||
character.head = headBone;
|
resolvedHand = FindChildBone(model.transform, "hand_r") ?? FindChildBone(model.transform, "RightHand");
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
character.head = FindChildBone(model.transform, "Head");
|
|
||||||
}
|
|
||||||
|
|
||||||
//Animator
|
|
||||||
var modelAnimator = model.GetComponent<Animator>();
|
var modelAnimator = model.GetComponent<Animator>();
|
||||||
if (modelAnimator != null && modelAnimator.avatar != null)
|
if (modelAnimator != null && modelAnimator.avatar != null)
|
||||||
{
|
{
|
||||||
@@ -178,121 +211,149 @@ public class PlayerBuilderTool : EditorWindow
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Голова если не найдена
|
// Кость головы (или создаём точку)
|
||||||
if (character.head == null)
|
if (resolvedHead == null)
|
||||||
{
|
{
|
||||||
GameObject headObj = new GameObject("HeadPoint");
|
var headObj = new GameObject("HeadPoint");
|
||||||
headObj.transform.SetParent(model != null ? model.transform : player.transform);
|
headObj.transform.SetParent(player.transform);
|
||||||
headObj.transform.localPosition = new Vector3(0, height - 0.2f, 0);
|
headObj.transform.localPosition = new Vector3(0, height - 0.2f, 0);
|
||||||
character.head = headObj.transform;
|
resolvedHead = headObj.transform;
|
||||||
}
|
}
|
||||||
|
character.head = resolvedHead;
|
||||||
|
|
||||||
// Камера
|
// Камера
|
||||||
if (addCamera && character.head != null)
|
if (addCamera)
|
||||||
{
|
{
|
||||||
GameObject cameraObj = new GameObject("PlayerCamera");
|
var camObj = new GameObject("PlayerCamera");
|
||||||
cameraObj.transform.SetParent(character.head);
|
camObj.transform.SetParent(resolvedHead);
|
||||||
cameraObj.transform.localPosition = new Vector3(0, 0.1f, 0);
|
camObj.transform.localPosition = new Vector3(0, 0.1f, 0);
|
||||||
|
var cam = camObj.AddComponent<Camera>();
|
||||||
var cam = cameraObj.AddComponent<Camera>();
|
|
||||||
cam.tag = "MainCamera";
|
cam.tag = "MainCamera";
|
||||||
cam.nearClipPlane = 0.1f;
|
cam.nearClipPlane = 0.05f;
|
||||||
|
|
||||||
// Удалить старую
|
|
||||||
var oldCam = GameObject.FindWithTag("MainCamera");
|
var oldCam = GameObject.FindWithTag("MainCamera");
|
||||||
if (oldCam != null && oldCam != cameraObj)
|
if (oldCam != null && oldCam != camObj)
|
||||||
{
|
|
||||||
DestroyImmediate(oldCam);
|
DestroyImmediate(oldCam);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// PlayerInput
|
||||||
|
var piGO = new GameObject("PlayerInput");
|
||||||
|
var pi = piGO.AddComponent<PlayerInput>();
|
||||||
|
if (inputActions != null) pi.actions = inputActions;
|
||||||
|
|
||||||
|
// HandEquipSystem
|
||||||
|
if (resolvedHand != null)
|
||||||
|
{
|
||||||
|
var handEquip = player.AddComponent<HandEquipSystem>();
|
||||||
|
handEquip.handBone = resolvedHand;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Debug.LogWarning("[PlayerBuilder] Кость руки не найдена — HandEquipSystem не добавлен. Назначьте вручную.");
|
||||||
}
|
}
|
||||||
|
|
||||||
// Тег
|
|
||||||
player.tag = "Player";
|
player.tag = "Player";
|
||||||
|
|
||||||
// Позиция
|
|
||||||
player.transform.position = new Vector3(0, 2, -5);
|
player.transform.position = new Vector3(0, 2, -5);
|
||||||
|
|
||||||
|
// Инвентарь
|
||||||
|
if (includeInventory)
|
||||||
|
SetupInventoryForPlayer(player);
|
||||||
|
|
||||||
|
return player;
|
||||||
|
}
|
||||||
|
|
||||||
|
void BuildPlayer(string name)
|
||||||
|
{
|
||||||
|
var player = BuildPlayerGO(name);
|
||||||
Selection.activeGameObject = player;
|
Selection.activeGameObject = player;
|
||||||
Debug.Log($"[PlayerBuilder] Создан: {playerName}");
|
Debug.Log($"[PlayerBuilder] Создан: {name}");
|
||||||
}
|
|
||||||
|
|
||||||
void SaveAsPrefab()
|
|
||||||
{
|
|
||||||
string path = EditorUtility.SaveFilePanelInProject(
|
|
||||||
"Сохранить префаб",
|
|
||||||
"Player",
|
|
||||||
"prefab",
|
|
||||||
"Выберите место");
|
|
||||||
|
|
||||||
if (string.IsNullOrEmpty(path)) return;
|
|
||||||
|
|
||||||
BuildPlayer("PlayerTemp");
|
|
||||||
|
|
||||||
GameObject player = GameObject.Find("PlayerTemp");
|
|
||||||
if (player == null)
|
|
||||||
{
|
|
||||||
Debug.LogError("Не удалось создать игрока");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
GameObject prefab = PrefabUtility.SaveAsPrefabAsset(player, path);
|
|
||||||
DestroyImmediate(player);
|
|
||||||
|
|
||||||
Selection.activeObject = prefab;
|
|
||||||
Debug.Log($"[PlayerBuilder] Сохранено: {path}");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void BuildTestPlayer()
|
void BuildTestPlayer()
|
||||||
{
|
{
|
||||||
|
var savedModel = characterModel;
|
||||||
characterModel = null;
|
characterModel = null;
|
||||||
headBone = null;
|
var player = BuildPlayerGO("TestPlayer");
|
||||||
BuildPlayer("TestPlayer");
|
characterModel = savedModel;
|
||||||
|
|
||||||
GameObject player = Selection.activeGameObject;
|
// Визуальная капсула
|
||||||
if (player == null) return;
|
var body = GameObject.CreatePrimitive(PrimitiveType.Capsule);
|
||||||
|
|
||||||
// Создаём визуальную часть
|
|
||||||
GameObject body = GameObject.CreatePrimitive(PrimitiveType.Capsule);
|
|
||||||
body.name = "Body";
|
body.name = "Body";
|
||||||
body.transform.SetParent(player.transform);
|
body.transform.SetParent(player.transform, false);
|
||||||
body.transform.localPosition = Vector3.zero;
|
body.transform.localPosition = new Vector3(0, centerY, 0);
|
||||||
|
body.transform.localScale = new Vector3(radius * 2, height / 2f, radius * 2);
|
||||||
DestroyImmediate(body.GetComponent<Collider>());
|
DestroyImmediate(body.GetComponent<Collider>());
|
||||||
|
|
||||||
GameObject head = new GameObject("Head");
|
Selection.activeGameObject = player;
|
||||||
head.transform.SetParent(player.transform);
|
Debug.Log("[PlayerBuilder] Создан тестовый игрок (капсула)");
|
||||||
head.transform.localPosition = new Vector3(0, centerY + 0.2f, 0);
|
}
|
||||||
|
|
||||||
var character = player.GetComponent<charecter>();
|
void SaveAsPrefab()
|
||||||
if (character != null)
|
|
||||||
{
|
{
|
||||||
character.head = head.transform;
|
string path = EditorUtility.SaveFilePanelInProject("Сохранить префаб", "Player", "prefab", "Выберите место");
|
||||||
|
if (string.IsNullOrEmpty(path)) return;
|
||||||
|
|
||||||
|
var temp = BuildPlayerGO("PlayerTemp");
|
||||||
|
var prefab = PrefabUtility.SaveAsPrefabAsset(temp, path);
|
||||||
|
DestroyImmediate(temp);
|
||||||
|
Selection.activeObject = prefab;
|
||||||
|
Debug.Log($"[PlayerBuilder] Сохранено: {path}");
|
||||||
}
|
}
|
||||||
|
|
||||||
if (addCamera)
|
// ── Создание инвентаря ────────────────────────────────────────────────────
|
||||||
|
|
||||||
|
void SetupInventoryForPlayer(GameObject player)
|
||||||
{
|
{
|
||||||
GameObject camObj = new GameObject("PlayerCamera");
|
// EventSystem
|
||||||
camObj.transform.SetParent(head.transform);
|
if (FindObjectOfType<EventSystem>() == null)
|
||||||
camObj.transform.localPosition = new Vector3(0, 0.1f, 0);
|
|
||||||
var cam = camObj.AddComponent<Camera>();
|
|
||||||
cam.tag = "MainCamera";
|
|
||||||
|
|
||||||
var oldCam = GameObject.FindWithTag("MainCamera");
|
|
||||||
if (oldCam != null && oldCam != camObj)
|
|
||||||
{
|
{
|
||||||
DestroyImmediate(oldCam);
|
var esGO = new GameObject("EventSystem");
|
||||||
}
|
esGO.AddComponent<EventSystem>();
|
||||||
|
esGO.AddComponent<StandaloneInputModule>();
|
||||||
}
|
}
|
||||||
|
|
||||||
Debug.Log("[PlayerBuilder] Создан тестовый игрок");
|
// InventoryEvents
|
||||||
|
new GameObject("InventoryEvents").AddComponent<InventoryEvents>();
|
||||||
|
|
||||||
|
// InventoryManager
|
||||||
|
var imGO = new GameObject("InventoryManager");
|
||||||
|
var im = imGO.AddComponent<InventoryManager>();
|
||||||
|
im.inventorySize = inventorySlots;
|
||||||
|
|
||||||
|
// InventoryCanvas — дочерний объект Player
|
||||||
|
var canvasGO = new GameObject("InventoryCanvas");
|
||||||
|
canvasGO.transform.SetParent(player.transform, false);
|
||||||
|
|
||||||
|
var canvas = canvasGO.AddComponent<Canvas>();
|
||||||
|
canvas.renderMode = RenderMode.ScreenSpaceOverlay;
|
||||||
|
canvas.sortingOrder = 100;
|
||||||
|
canvasGO.AddComponent<UnityEngine.UI.GraphicRaycaster>();
|
||||||
|
|
||||||
|
var uiBuilder = canvasGO.AddComponent<InventoryUIBuilder>();
|
||||||
|
uiBuilder.inventoryRows = inventorySlots / 9;
|
||||||
|
uiBuilder.hotbarSlots = hotbarSlots;
|
||||||
|
|
||||||
|
// Строим UI сразу до запуска игры
|
||||||
|
uiBuilder.BuildInventoryUI();
|
||||||
|
|
||||||
|
// Назначаем ссылки в InventoryManager
|
||||||
|
im.slots = uiBuilder.GetInventorySlots();
|
||||||
|
im.hotbarSlots = uiBuilder.GetHotbarSlots();
|
||||||
|
im.inventoryPanel = uiBuilder.inventoryPanelRect != null ? uiBuilder.inventoryPanelRect.gameObject : null;
|
||||||
|
im.inventoryCanvas = canvas;
|
||||||
|
|
||||||
|
if (im.inventoryPanel != null)
|
||||||
|
im.inventoryPanel.SetActive(false);
|
||||||
|
|
||||||
|
Debug.Log("[PlayerBuilder] Инвентарь создан и назначен.");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ── Утилиты ───────────────────────────────────────────────────────────────
|
||||||
|
|
||||||
Transform FindChildBone(Transform parent, string boneName)
|
Transform FindChildBone(Transform parent, string boneName)
|
||||||
{
|
{
|
||||||
if (parent == null) return null;
|
if (parent == null) return null;
|
||||||
|
if (parent.name.ToLower().Contains(boneName.ToLower())) return parent;
|
||||||
if (parent.name.ToLower().Contains(boneName.ToLower()))
|
|
||||||
return parent;
|
|
||||||
|
|
||||||
foreach (Transform child in parent)
|
foreach (Transform child in parent)
|
||||||
{
|
{
|
||||||
var result = FindChildBone(child, boneName);
|
var result = FindChildBone(child, boneName);
|
||||||
|
|||||||
@@ -1,29 +1,51 @@
|
|||||||
using UnityEngine;
|
using UnityEngine;
|
||||||
using System;
|
using System;
|
||||||
|
using UnityEngine.InputSystem;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Централизованный ввод на основе New Input System.
|
||||||
|
/// Singleton, DontDestroyOnLoad.
|
||||||
|
/// Биндинги сохраняются в PlayerPrefs автоматически при изменении.
|
||||||
|
/// </summary>
|
||||||
public class PlayerInput : MonoBehaviour
|
public class PlayerInput : MonoBehaviour
|
||||||
{
|
{
|
||||||
public static PlayerInput Instance { get; private set; }
|
public static PlayerInput Instance { get; private set; }
|
||||||
|
|
||||||
// Continuous axes
|
// ── Ссылка на InputActionAsset ────────────────────────────────────────────
|
||||||
public float MouseX { get; private set; }
|
[Tooltip("Назначьте Assets/Input/PlayerControls.inputactions")]
|
||||||
public float MouseY { get; private set; }
|
public InputActionAsset actions;
|
||||||
public float Horizontal { get; private set; }
|
|
||||||
public float Vertical { get; private set; }
|
|
||||||
|
|
||||||
// Continuous states
|
// ── Непрерывные значения ──────────────────────────────────────────────────
|
||||||
|
public Vector2 MoveInput { get; private set; }
|
||||||
|
public Vector2 LookInput { get; private set; }
|
||||||
public bool Crouch { get; private set; }
|
public bool Crouch { get; private set; }
|
||||||
public bool Run { get; private set; }
|
public bool Run { get; private set; }
|
||||||
|
|
||||||
// Events for discrete actions
|
// ── Дискретные события ────────────────────────────────────────────────────
|
||||||
public event Action OnToggleInventory;
|
public event Action OnToggleInventory;
|
||||||
public event Action OnDropPressed;
|
public event Action OnDropPressed;
|
||||||
public event Action OnPickupPressed;
|
public event Action OnPickupPressed;
|
||||||
public event Action OnJumpPressed;
|
public event Action OnJumpPressed;
|
||||||
public event Action<int> OnHotbarSelect;
|
public event Action<int> OnHotbarSelect;
|
||||||
|
|
||||||
public bool Enabled { get; set; } = true;
|
// ── Включение/выключение gameplay-ввода (инвентарь открыт) ───────────────
|
||||||
|
public bool Enabled
|
||||||
|
{
|
||||||
|
get => _gameplayMap != null && _gameplayMap.enabled;
|
||||||
|
set
|
||||||
|
{
|
||||||
|
if (_gameplayMap == null) return;
|
||||||
|
if (value) _gameplayMap.Enable();
|
||||||
|
else _gameplayMap.Disable();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// ── Приватные поля ────────────────────────────────────────────────────────
|
||||||
|
private InputActionMap _gameplayMap;
|
||||||
|
private InputActionMap _uiMap;
|
||||||
|
private const string BINDINGS_PREF_KEY = "PlayerBindings_v1";
|
||||||
|
|
||||||
|
// ── Lifecycle ─────────────────────────────────────────────────────────────
|
||||||
void Awake()
|
void Awake()
|
||||||
{
|
{
|
||||||
if (Instance == null)
|
if (Instance == null)
|
||||||
@@ -34,46 +56,116 @@ public class PlayerInput : MonoBehaviour
|
|||||||
else
|
else
|
||||||
{
|
{
|
||||||
Destroy(gameObject);
|
Destroy(gameObject);
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (actions == null)
|
||||||
|
{
|
||||||
|
actions = Resources.Load<InputActionAsset>("PlayerControls");
|
||||||
|
if (actions == null)
|
||||||
|
{
|
||||||
|
Debug.LogError("[PlayerInput] PlayerControls.inputactions не назначен и не найден в Resources!");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Создаём рабочую копию чтобы не менять оригинальный asset
|
||||||
|
actions = Instantiate(actions);
|
||||||
|
|
||||||
|
// Загрузить сохранённые биндинги
|
||||||
|
var saved = PlayerPrefs.GetString(BINDINGS_PREF_KEY, "");
|
||||||
|
if (!string.IsNullOrEmpty(saved))
|
||||||
|
actions.LoadBindingOverridesFromJson(saved);
|
||||||
|
|
||||||
|
_gameplayMap = actions.FindActionMap("Gameplay", throwIfNotFound: true);
|
||||||
|
_uiMap = actions.FindActionMap("UI", throwIfNotFound: true);
|
||||||
|
|
||||||
|
// Подписка: дискретные кнопки
|
||||||
|
_gameplayMap["Jump"].performed += _ => OnJumpPressed?.Invoke();
|
||||||
|
_gameplayMap["Pickup"].performed += _ => OnPickupPressed?.Invoke();
|
||||||
|
_gameplayMap["Drop"].performed += _ => OnDropPressed?.Invoke();
|
||||||
|
|
||||||
|
// UI map всегда активна — нет double-fire бага
|
||||||
|
_uiMap["ToggleInventory"].performed += _ => OnToggleInventory?.Invoke();
|
||||||
|
_uiMap["CloseInventory"].performed += _ => OnToggleInventory?.Invoke();
|
||||||
|
|
||||||
|
for (int i = 0; i < 9; i++)
|
||||||
|
{
|
||||||
|
int idx = i;
|
||||||
|
_gameplayMap[$"Hotbar{idx}"].performed += _ => OnHotbarSelect?.Invoke(idx);
|
||||||
|
}
|
||||||
|
|
||||||
|
_gameplayMap.Enable();
|
||||||
|
_uiMap.Enable();
|
||||||
|
}
|
||||||
|
|
||||||
|
void OnDestroy()
|
||||||
|
{
|
||||||
|
_gameplayMap?.Disable();
|
||||||
|
_uiMap?.Disable();
|
||||||
}
|
}
|
||||||
|
|
||||||
void Update()
|
void Update()
|
||||||
{
|
{
|
||||||
// Always allow toggle inventory (Tab/Escape) even when input is disabled
|
if (_gameplayMap == null || !_gameplayMap.enabled) return;
|
||||||
if (Input.GetKeyDown(KeyCode.Tab) || Input.GetKeyDown(KeyCode.Escape))
|
|
||||||
OnToggleInventory?.Invoke();
|
|
||||||
|
|
||||||
if (!Enabled) return;
|
MoveInput = _gameplayMap["Move"].ReadValue<Vector2>();
|
||||||
|
LookInput = _gameplayMap["Look"].ReadValue<Vector2>();
|
||||||
|
Crouch = _gameplayMap["Crouch"].IsPressed();
|
||||||
|
Run = _gameplayMap["Run"].IsPressed();
|
||||||
|
}
|
||||||
|
|
||||||
// Axes
|
// ── Сохранение/загрузка биндингов ────────────────────────────────────────
|
||||||
MouseX = Input.GetAxis("Mouse X");
|
|
||||||
MouseY = Input.GetAxis("Mouse Y");
|
|
||||||
Horizontal = Input.GetAxisRaw("Horizontal");
|
|
||||||
Vertical = Input.GetAxisRaw("Vertical");
|
|
||||||
|
|
||||||
// Continuous keys
|
[ContextMenu("Save Bindings")]
|
||||||
Crouch = Input.GetKey(KeyCode.C);
|
public void SaveBindings()
|
||||||
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))
|
if (actions == null) return;
|
||||||
|
PlayerPrefs.SetString(BINDINGS_PREF_KEY, actions.SaveBindingOverridesAsJson());
|
||||||
|
PlayerPrefs.Save();
|
||||||
|
Debug.Log("[PlayerInput] Биндинги сохранены");
|
||||||
|
}
|
||||||
|
|
||||||
|
[ContextMenu("Reset Bindings to Defaults")]
|
||||||
|
public void ResetBindings()
|
||||||
{
|
{
|
||||||
OnHotbarSelect?.Invoke(i);
|
if (actions == null) return;
|
||||||
|
foreach (var action in actions)
|
||||||
|
action.RemoveAllBindingOverrides();
|
||||||
|
PlayerPrefs.DeleteKey(BINDINGS_PREF_KEY);
|
||||||
|
Debug.Log("[PlayerInput] Биндинги сброшены к умолчаниям");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Интерактивный ремаппинг. Передайте имя action, имя map и callback для UI.
|
||||||
|
/// Пример: StartRebind("Jump", "Gameplay", () => UpdateUI());
|
||||||
|
/// </summary>
|
||||||
|
public void StartRebind(string actionName, string mapName, Action onComplete)
|
||||||
|
{
|
||||||
|
var map = actions?.FindActionMap(mapName);
|
||||||
|
var action = map?.FindAction(actionName);
|
||||||
|
if (action == null)
|
||||||
|
{
|
||||||
|
Debug.LogWarning($"[PlayerInput] Действие '{actionName}' в map '{mapName}' не найдено");
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
action.Disable();
|
||||||
|
action.PerformInteractiveRebinding()
|
||||||
|
.WithControlsExcluding("<Mouse>/position")
|
||||||
|
.WithControlsExcluding("<Mouse>/delta")
|
||||||
|
.OnComplete(op =>
|
||||||
|
{
|
||||||
|
op.Dispose();
|
||||||
|
action.Enable();
|
||||||
|
SaveBindings();
|
||||||
|
onComplete?.Invoke();
|
||||||
|
})
|
||||||
|
.Start();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Доступ к InputActionAsset для UI-ремаппинга и отображения текущих биндингов.
|
||||||
|
/// </summary>
|
||||||
|
public InputActionAsset GetActions() => actions;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -46,19 +46,20 @@ public class charecter : MonoBehaviour
|
|||||||
_cc = GetComponent<CharacterController>();
|
_cc = GetComponent<CharacterController>();
|
||||||
_anim = GetComponentInChildren<Animator>();
|
_anim = GetComponentInChildren<Animator>();
|
||||||
Cursor.lockState = CursorLockMode.Locked;
|
Cursor.lockState = CursorLockMode.Locked;
|
||||||
|
Cursor.visible = false;
|
||||||
|
|
||||||
_bodyYaw = transform.eulerAngles.y;
|
_bodyYaw = transform.eulerAngles.y;
|
||||||
_headYaw = _bodyYaw;
|
_headYaw = _bodyYaw;
|
||||||
_headBindPose = head.localRotation;
|
_headBindPose = head != null ? head.localRotation : Quaternion.identity;
|
||||||
|
|
||||||
// Ensure PlayerInput exists and subscribe to events
|
// Убедиться что PlayerInput существует
|
||||||
if (PlayerInput.Instance == null)
|
if (PlayerInput.Instance == null)
|
||||||
{
|
{
|
||||||
var go = new GameObject("PlayerInput");
|
var go = new GameObject("PlayerInput");
|
||||||
go.AddComponent<PlayerInput>();
|
go.AddComponent<PlayerInput>();
|
||||||
}
|
}
|
||||||
|
|
||||||
PlayerInput.Instance.OnPickupPressed += () => TryPickupNearbyItem();
|
PlayerInput.Instance.OnPickupPressed += TryPickupNearbyItem;
|
||||||
PlayerInput.Instance.OnJumpPressed += () => { _jumpRequested = true; };
|
PlayerInput.Instance.OnJumpPressed += () => { _jumpRequested = true; };
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -68,55 +69,35 @@ public class charecter : MonoBehaviour
|
|||||||
HandleMovement();
|
HandleMovement();
|
||||||
}
|
}
|
||||||
|
|
||||||
// ── Item Pickup ───────────────────────────────────────────────────────────
|
void LateUpdate()
|
||||||
void HandlePickup()
|
|
||||||
{
|
{
|
||||||
// Input moved to PlayerInput events
|
ApplyRotations();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ── Item Pickup ───────────────────────────────────────────────────────────
|
||||||
void TryPickupNearbyItem()
|
void TryPickupNearbyItem()
|
||||||
{
|
{
|
||||||
float pickupRadius = 2.5f;
|
float pickupRadius = 2.5f;
|
||||||
Collider[] colliders = Physics.OverlapSphere(transform.position, pickupRadius);
|
Collider[] colliders = Physics.OverlapSphere(transform.position, pickupRadius);
|
||||||
|
|
||||||
Debug.Log($"[Pickup] Checking {colliders.Length} colliders in radius {pickupRadius}");
|
|
||||||
|
|
||||||
WorldItem closestItem = null;
|
WorldItem closestItem = null;
|
||||||
float closestDist = float.MaxValue;
|
float closestDist = float.MaxValue;
|
||||||
|
|
||||||
foreach (var col in colliders)
|
foreach (var col in colliders)
|
||||||
{
|
{
|
||||||
var worldItem = col.GetComponent<WorldItem>();
|
var worldItem = col.GetComponent<WorldItem>();
|
||||||
if (worldItem != null)
|
if (worldItem == null) continue;
|
||||||
{
|
|
||||||
float dist = Vector3.Distance(transform.position, worldItem.transform.position);
|
float dist = Vector3.Distance(transform.position, worldItem.transform.position);
|
||||||
Debug.Log($"[Pickup] Found WorldItem: {worldItem.itemData?.itemName ?? "null"} at dist {dist}");
|
if (dist < closestDist && dist <= worldItem.interactRange)
|
||||||
if (dist < closestDist)
|
|
||||||
{
|
{
|
||||||
closestDist = dist;
|
closestDist = dist;
|
||||||
closestItem = worldItem;
|
closestItem = worldItem;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
if (closestItem != null)
|
if (closestItem != null)
|
||||||
{
|
closestItem.TryPickupByButton();
|
||||||
Debug.Log($"[Pickup] Trying to pick up: {closestItem.itemData?.itemName}");
|
|
||||||
bool pickedUp = closestItem.TryPickupByButton();
|
|
||||||
if (pickedUp)
|
|
||||||
{
|
|
||||||
Debug.Log($"Picked up: {closestItem.itemData.itemName}");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
Debug.Log("[Pickup] No WorldItem found nearby");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void LateUpdate()
|
|
||||||
{
|
|
||||||
ApplyRotations();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// ── Mouse look ────────────────────────────────────────────────────────────
|
// ── Mouse look ────────────────────────────────────────────────────────────
|
||||||
@@ -125,8 +106,8 @@ public class charecter : MonoBehaviour
|
|||||||
var input = PlayerInput.Instance;
|
var input = PlayerInput.Instance;
|
||||||
if (input != null)
|
if (input != null)
|
||||||
{
|
{
|
||||||
_headYaw += input.MouseX * mouseSensitivity;
|
_headYaw += input.LookInput.x * mouseSensitivity;
|
||||||
_pitch -= input.MouseY * mouseSensitivity;
|
_pitch -= input.LookInput.y * mouseSensitivity;
|
||||||
}
|
}
|
||||||
_pitch = Mathf.Clamp(_pitch, -maxPitch, maxPitch);
|
_pitch = Mathf.Clamp(_pitch, -maxPitch, maxPitch);
|
||||||
}
|
}
|
||||||
@@ -135,11 +116,11 @@ public class charecter : MonoBehaviour
|
|||||||
void HandleMovement()
|
void HandleMovement()
|
||||||
{
|
{
|
||||||
var input = PlayerInput.Instance;
|
var input = PlayerInput.Instance;
|
||||||
float h = input != null ? input.Horizontal : Input.GetAxisRaw("Horizontal");
|
float h = input != null ? input.MoveInput.x : 0f;
|
||||||
float v = input != null ? input.Vertical : Input.GetAxisRaw("Vertical");
|
float v = input != null ? input.MoveInput.y : 0f;
|
||||||
|
|
||||||
bool isCrouching = input != null ? input.Crouch : Input.GetKey(KeyCode.C);
|
bool isCrouching = input != null && input.Crouch;
|
||||||
bool isRunning = input != null ? input.Run && !isCrouching : Input.GetKey(KeyCode.LeftShift) && !isCrouching;
|
bool isRunning = input != null && input.Run && !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;
|
||||||
@@ -148,7 +129,7 @@ public class charecter : MonoBehaviour
|
|||||||
if (isMoving)
|
if (isMoving)
|
||||||
_bodyYaw = Mathf.MoveTowardsAngle(_bodyYaw, _headYaw, bodyAlignSpeed * Time.deltaTime);
|
_bodyYaw = Mathf.MoveTowardsAngle(_bodyYaw, _headYaw, bodyAlignSpeed * Time.deltaTime);
|
||||||
|
|
||||||
// Head-drag
|
// Head-drag clamp
|
||||||
float offset = Mathf.DeltaAngle(_bodyYaw, _headYaw);
|
float offset = Mathf.DeltaAngle(_bodyYaw, _headYaw);
|
||||||
float clampedOffset = Mathf.Clamp(offset, -maxHeadYaw, maxHeadYaw);
|
float clampedOffset = Mathf.Clamp(offset, -maxHeadYaw, maxHeadYaw);
|
||||||
_bodyYaw += offset - clampedOffset;
|
_bodyYaw += offset - clampedOffset;
|
||||||
@@ -176,10 +157,9 @@ public class charecter : MonoBehaviour
|
|||||||
moveDir.y = _verticalVelocity;
|
moveDir.y = _verticalVelocity;
|
||||||
_cc.Move(moveDir * speed * Time.deltaTime);
|
_cc.Move(moveDir * speed * Time.deltaTime);
|
||||||
|
|
||||||
// Animator params
|
// Animator
|
||||||
if (_anim != null)
|
if (_anim != null)
|
||||||
{
|
{
|
||||||
// Speed: 0 = idle, 0.5 = walk, 1 = run
|
|
||||||
float animSpeed = !isMoving ? 0f : isRunning ? 1f : 0.5f;
|
float animSpeed = !isMoving ? 0f : isRunning ? 1f : 0.5f;
|
||||||
_anim.SetFloat(HashSpeed, animSpeed, 0.1f, Time.deltaTime);
|
_anim.SetFloat(HashSpeed, animSpeed, 0.1f, Time.deltaTime);
|
||||||
_anim.SetBool (HashIsMoving, isMoving);
|
_anim.SetBool (HashIsMoving, isMoving);
|
||||||
@@ -193,10 +173,11 @@ public class charecter : MonoBehaviour
|
|||||||
{
|
{
|
||||||
transform.rotation = Quaternion.Euler(0f, _bodyYaw, 0f);
|
transform.rotation = Quaternion.Euler(0f, _bodyYaw, 0f);
|
||||||
|
|
||||||
|
if (head == null) return;
|
||||||
|
|
||||||
float headOffset = Mathf.DeltaAngle(_bodyYaw, _headYaw);
|
float headOffset = Mathf.DeltaAngle(_bodyYaw, _headYaw);
|
||||||
Quaternion yawRot = Quaternion.Euler(0f, headOffset, 0f);
|
Quaternion yawRot = Quaternion.Euler(0f, headOffset, 0f);
|
||||||
Quaternion pitchRot = Quaternion.Euler(_pitch, 0f, 0f);
|
Quaternion pitchRot = Quaternion.Euler(_pitch, 0f, 0f);
|
||||||
head.localRotation = _headBindPose * yawRot * pitchRot;
|
head.localRotation = _headBindPose * yawRot * pitchRot;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
107
CLAUDE.md
107
CLAUDE.md
@@ -4,64 +4,69 @@ This file provides guidance to Claude Code (claude.ai/code) when working with co
|
|||||||
|
|
||||||
## Project Overview
|
## Project Overview
|
||||||
|
|
||||||
This is a Unity game project with two major systems:
|
Unity game project (no CLI build commands — use the Unity Editor). Two major systems:
|
||||||
1. **Character Controller** - First/third-person movement with animations
|
1. **Character Controller** — first/third-person movement with animations
|
||||||
2. **Inventory System** - Full inventory with hotbar, drag-drop, crafting, and item generation
|
2. **Inventory System** — hotbar, drag-drop, crafting, world items, save/load
|
||||||
|
|
||||||
## Controls
|
## Controls
|
||||||
|
|
||||||
- **Movement**: WASD
|
| Action | Key |
|
||||||
- **Look**: Mouse
|
|---|---|
|
||||||
- **Run**: Left Shift
|
| Move | WASD |
|
||||||
- **Crouch**: C
|
| Look | Mouse |
|
||||||
- **Jump**: Space
|
| Run | Left Shift |
|
||||||
- **Toggle Inventory**: Tab
|
| Crouch | C |
|
||||||
- **Close Inventory**: Escape
|
| Jump | Space |
|
||||||
- **Hotbar Selection**: 1-9 keys
|
| Pickup | E |
|
||||||
- **Drop Item**: Q
|
| Toggle Inventory | Tab |
|
||||||
|
| Close Inventory | Escape |
|
||||||
## Key Files and Structure
|
| Hotbar Select | 1–9 |
|
||||||
|
| Drop Item | Q |
|
||||||
### Character Controller (`Assets/charecter-controller/scripts/`)
|
|
||||||
- `charecter.cs` - Main character controller with movement, jumping, crouching, mouse look
|
|
||||||
- `PlayerBuilder.cs` - Player setup utility
|
|
||||||
- `PlayerBuilderTool.cs` - Editor tool for building player objects
|
|
||||||
|
|
||||||
### Inventory System (`Assets/Inventory/Scripts/`)
|
|
||||||
- `InventoryManager.cs` - Core inventory logic (singleton, item operations, save/load)
|
|
||||||
- `Slot.cs` - Individual inventory slot with stacking logic
|
|
||||||
- `ItemData.cs` - Item definition (id, name, icon, maxStack, etc.)
|
|
||||||
- `InventoryEvents.cs` - Centralized event system for inventory changes
|
|
||||||
- `InventoryItemFactory.cs` - Creates dropped items in the world
|
|
||||||
- `InventoryDragDrop.cs` - Drag and drop UI handling
|
|
||||||
- `CraftingManager.cs` - Recipe-based crafting system
|
|
||||||
- `InventoryUIBuilder.cs` - Runtime UI generation
|
|
||||||
|
|
||||||
### Scene
|
|
||||||
- `Assets/Scenes/SampleScene.unity` - Main test scene
|
|
||||||
|
|
||||||
## Architecture
|
## Architecture
|
||||||
|
|
||||||
### Character Controller Design
|
### Input Layer — `PlayerInput` (singleton, DontDestroyOnLoad)
|
||||||
- Uses Unity's CharacterController component for collision
|
All input is centralised in `Assets/charecter-controller/scripts/PlayerInput.cs`. It exposes:
|
||||||
- Head-body separation: body rotates toward look direction, head can offset within limits
|
- Continuous properties: `MouseX`, `MouseY`, `Horizontal`, `Vertical`, `Crouch`, `Run`
|
||||||
- Animator parameters use `Animator.StringToHash` for performance (Speed, IsMoving, IsCrouching, IsGrounded, Jump)
|
- C# events: `OnJumpPressed`, `OnPickupPressed`, `OnToggleInventory`, `OnDropPressed`, `OnHotbarSelect`
|
||||||
- Physics-based jumping: `v = sqrt(jumpHeight * -2 * gravity)`
|
- `Enabled` flag — set to `false` when the inventory is open to block gameplay input
|
||||||
- All movement is framerate-independent with `Time.deltaTime`
|
|
||||||
|
|
||||||
### Inventory Architecture
|
Both `charecter.cs` and `InventoryManager.cs` subscribe to `PlayerInput.Instance` events in `Start()`. Never read `Input.*` directly in new code — go through `PlayerInput`.
|
||||||
- **Singleton pattern**: `InventoryManager.Instance` persists across scenes (DontDestroyOnLoad)
|
|
||||||
- **Dual storage**: Main inventory (36 slots) + Hotbar (9 slots, indices 0-8)
|
|
||||||
- **Item lookup**: `_itemDict` dictionary maps item IDs to ItemData
|
|
||||||
- **Stacking**: Items stack up to `maxStack` defined in ItemData
|
|
||||||
- **Events**: InventoryEvents provides OnItemAdded, OnItemRemoved, OnInventoryOpened/Closed
|
|
||||||
|
|
||||||
### Inventory Flow
|
### Character Controller — `charecter.cs`
|
||||||
1. Items added via `AddItem(itemId, amount)` - tries existing stacks first, then empty slots
|
- Requires `CharacterController` component
|
||||||
2. Removed via `RemoveItem(itemId, amount)` - returns true if successful
|
- Head-bone / body separation: body yaw tracks camera yaw when moving; head offset is clamped to `±maxHeadYaw`
|
||||||
3. Hotbar selection via `SelectHotbarSlot(index)` - updates visual selection
|
- Bone rotations applied in `LateUpdate` via `ApplyRotations()`
|
||||||
4. Item dropped via `DropSelectedItem()` - spawns world object via InventoryItemFactory
|
- Animator hashes cached as `static readonly int` fields; animator Speed param: 0 = idle, 0.5 = walk, 1 = run
|
||||||
5. JSON serialization via `ExportToJson()` / `ImportFromJson()`
|
- Item pickup radius-cast in `TryPickupNearbyItem()` (2.5 m sphere, closest `WorldItem` wins)
|
||||||
|
|
||||||
|
### Inventory System
|
||||||
|
**Singleton chain** (all DontDestroyOnLoad, all auto-created if missing):
|
||||||
|
```
|
||||||
|
PlayerInput → InventoryManager → InventoryItemFactory
|
||||||
|
→ InventoryEvents
|
||||||
|
```
|
||||||
|
|
||||||
|
**InventoryManager** (`Assets/Inventory/Scripts/InventoryManager.cs`)
|
||||||
|
- `slots[]` (36) = main inventory; `hotbarSlots[]` (9, indices 0-8)
|
||||||
|
- `_itemDict` maps `ItemData.id → ItemData`; rebuilt via `RebuildItemDictionary()` — call this after runtime DB changes
|
||||||
|
- `AddItem()` fill order: existing main stacks → empty main slots → existing hotbar stacks → empty hotbar slots
|
||||||
|
- Save/load: JSON to `Application.persistentDataPath/inventory_save.json`; auto-save on `OnApplicationQuit`
|
||||||
|
|
||||||
|
**ItemData** — ScriptableObject (`Assets > Create > Inventory > Item`). `id` is auto-assigned as GUID on first `OnEnable`. ItemType enum: `Block, Weapon, Armor, Consumable, Tool, Material`.
|
||||||
|
|
||||||
|
**InventoryItemFactory** — creates/drops `WorldItem` GameObjects. Needs an `ItemFactoryConfig` ScriptableObject (`Assets > Create > Inventory > Item Factory Config`) assigned in the Inspector for prefab-based spawning; falls back to a primitive cube if no prefab is configured.
|
||||||
|
|
||||||
|
**CraftingManager** — recipe key is sorted comma-joined ingredient IDs (`"id1,id2,id3"`). Recipes can be added at runtime via `AddRecipe()`.
|
||||||
|
|
||||||
|
**InventoryUIBuilder** — generates the entire inventory UI programmatically at runtime (Canvas, GridLayoutGroup, Slot components, drag-drop handlers). Assigns `InventoryManager.Instance.slots` and `.hotbarSlots` directly. Do not assign these arrays in the Inspector when using this builder.
|
||||||
|
|
||||||
|
**InventorySetup** — convenience MonoBehaviour; add to a "GameManager" object to auto-create all managers and UI on scene start. Has an Editor button in the Inspector. Skips creation if `InventoryManager` already exists.
|
||||||
|
|
||||||
|
### Scene Setup
|
||||||
|
`Assets/Scenes/SampleScene.unity` is the only scene. Typical hierarchy:
|
||||||
|
- `GameManager` with `InventorySetup` (or manually placed `InventoryManager` + `InventoryUIBuilder`)
|
||||||
|
- Player with `charecter.cs` + `CharacterController` + Animator + head bone reference
|
||||||
|
|
||||||
### Meta Files
|
### Meta Files
|
||||||
Unity requires .meta files for all assets - always commit them alongside their assets.
|
Unity requires `.meta` files for all assets — always commit them alongside their assets.
|
||||||
|
|||||||
@@ -8,6 +8,7 @@
|
|||||||
"com.unity.collab-proxy": "2.12.4",
|
"com.unity.collab-proxy": "2.12.4",
|
||||||
"com.unity.ide.rider": "3.0.39",
|
"com.unity.ide.rider": "3.0.39",
|
||||||
"com.unity.ide.visualstudio": "2.0.27",
|
"com.unity.ide.visualstudio": "2.0.27",
|
||||||
|
"com.unity.inputsystem": "1.19.0",
|
||||||
"com.unity.multiplayer.center": "1.0.1",
|
"com.unity.multiplayer.center": "1.0.1",
|
||||||
"com.unity.purchasing": "4.15.0",
|
"com.unity.purchasing": "4.15.0",
|
||||||
"com.unity.test-framework": "1.6.0",
|
"com.unity.test-framework": "1.6.0",
|
||||||
|
|||||||
@@ -75,6 +75,15 @@
|
|||||||
},
|
},
|
||||||
"url": "https://packages.unity.com"
|
"url": "https://packages.unity.com"
|
||||||
},
|
},
|
||||||
|
"com.unity.inputsystem": {
|
||||||
|
"version": "1.19.0",
|
||||||
|
"depth": 0,
|
||||||
|
"source": "registry",
|
||||||
|
"dependencies": {
|
||||||
|
"com.unity.modules.uielements": "1.0.0"
|
||||||
|
},
|
||||||
|
"url": "https://packages.unity.com"
|
||||||
|
},
|
||||||
"com.unity.multiplayer.center": {
|
"com.unity.multiplayer.center": {
|
||||||
"version": "1.0.1",
|
"version": "1.0.1",
|
||||||
"depth": 0,
|
"depth": 0,
|
||||||
|
|||||||
@@ -5,5 +5,5 @@ EditorBuildSettings:
|
|||||||
m_ObjectHideFlags: 0
|
m_ObjectHideFlags: 0
|
||||||
serializedVersion: 2
|
serializedVersion: 2
|
||||||
m_Scenes: []
|
m_Scenes: []
|
||||||
m_configObjects: {}
|
m_configObjects:
|
||||||
m_UseUCBPForAssetBundles: 0
|
com.unity.input.settings.actions: {fileID: -944628639613478452, guid: 7d782555f7e02f84ca2502d52361f19a, type: 3}
|
||||||
|
|||||||
@@ -41,7 +41,6 @@ PlayerSettings:
|
|||||||
height: 1
|
height: 1
|
||||||
m_SplashScreenLogos: []
|
m_SplashScreenLogos: []
|
||||||
m_VirtualRealitySplashScreen: {fileID: 0}
|
m_VirtualRealitySplashScreen: {fileID: 0}
|
||||||
m_HolographicTrackingLossScreen: {fileID: 0}
|
|
||||||
defaultScreenWidth: 1920
|
defaultScreenWidth: 1920
|
||||||
defaultScreenHeight: 1080
|
defaultScreenHeight: 1080
|
||||||
defaultScreenWidthWeb: 960
|
defaultScreenWidthWeb: 960
|
||||||
@@ -148,12 +147,10 @@ PlayerSettings:
|
|||||||
preloadedAssets: []
|
preloadedAssets: []
|
||||||
metroInputSource: 0
|
metroInputSource: 0
|
||||||
wsaTransparentSwapchain: 0
|
wsaTransparentSwapchain: 0
|
||||||
m_HolographicPauseOnTrackingLoss: 1
|
|
||||||
xboxOneDisableKinectGpuReservation: 1
|
xboxOneDisableKinectGpuReservation: 1
|
||||||
xboxOneEnable7thCore: 1
|
xboxOneEnable7thCore: 1
|
||||||
vrSettings:
|
vrSettings:
|
||||||
enable360StereoCapture: 0
|
enable360StereoCapture: 0
|
||||||
isWsaHolographicRemotingEnabled: 0
|
|
||||||
enableFrameTimingStats: 0
|
enableFrameTimingStats: 0
|
||||||
enableOpenGLProfilerGPURecorders: 1
|
enableOpenGLProfilerGPURecorders: 1
|
||||||
allowHDRDisplaySupport: 0
|
allowHDRDisplaySupport: 0
|
||||||
@@ -762,8 +759,9 @@ PlayerSettings:
|
|||||||
qnxGraphicConfPath:
|
qnxGraphicConfPath:
|
||||||
apiCompatibilityLevel: 6
|
apiCompatibilityLevel: 6
|
||||||
captureStartupLogs: {}
|
captureStartupLogs: {}
|
||||||
activeInputHandler: 0
|
activeInputHandler: 2
|
||||||
windowsGamepadBackendHint: 0
|
windowsGamepadBackendHint: 0
|
||||||
|
enableDirectStorage: 0
|
||||||
cloudProjectId:
|
cloudProjectId:
|
||||||
framebufferDepthMemorylessMode: 0
|
framebufferDepthMemorylessMode: 0
|
||||||
qualitySettingsNames: []
|
qualitySettingsNames: []
|
||||||
|
|||||||
Reference in New Issue
Block a user