fix чать инвенторя
This commit is contained in:
@@ -1,8 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 91470f1965cf83a4a8c49831ec2f7691
|
||||
NativeFormatImporter:
|
||||
guid: 037877a8b07e2d84e8a888f939cfbab6
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
mainObjectFileID: 11400000
|
||||
userData:
|
||||
assetBundleName:
|
||||
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
|
||||
guid: 223ec2dc359ac0845957ab0b29284414
|
||||
guid: 9f444e9048146434087c3db3550617f9
|
||||
PrefabImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
@@ -12,9 +12,9 @@ MonoBehaviour:
|
||||
m_Script: {fileID: 11500000, guid: 5741b63764436354ebad192c9b71f06c, type: 3}
|
||||
m_Name: NewItem
|
||||
m_EditorClassIdentifier: Assembly-CSharp::ItemData
|
||||
id: 2
|
||||
id: d28a3db9-17bd-489d-9caf-739005a7c780
|
||||
itemName: NewItem
|
||||
description: 23
|
||||
description: 123
|
||||
type: 5
|
||||
modelPrefab: {fileID: 282714382156279063, guid: 4fcbba5b8725e254f98c052c4db89e02, type: 3}
|
||||
icon: {fileID: 21300000, guid: 0115b2d990086ae4cbc31baf7c64e680, type: 3}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
fileFormatVersion: 2
|
||||
guid: e9765c2fbc4980049940f96e9b0f70dc
|
||||
guid: 20cff4d8f616b1140b2264c6f049ba8a
|
||||
NativeFormatImporter:
|
||||
externalObjects: {}
|
||||
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,51 +78,33 @@ public class InventoryManager : MonoBehaviour
|
||||
|
||||
void Start()
|
||||
{
|
||||
// Инициализация слотов
|
||||
// Слоты созданы editor-инструментом и назначены в Inspector
|
||||
if (slots == null || slots.Length == 0)
|
||||
{
|
||||
Debug.LogWarning("Slots not assigned! Assign them in Inspector or use InventoryUIBuilder.");
|
||||
}
|
||||
Debug.LogWarning("[InventoryManager] Slots not assigned! Run Tools > Setup Complete Scene first.");
|
||||
else
|
||||
{
|
||||
foreach (var slot in slots)
|
||||
{
|
||||
slot?.UpdateSlotUI();
|
||||
}
|
||||
}
|
||||
foreach (var slot in slots) slot?.UpdateSlotUI();
|
||||
|
||||
if (hotbarSlots != null)
|
||||
{
|
||||
foreach (var slot in hotbarSlots)
|
||||
{
|
||||
slot?.UpdateSlotUI();
|
||||
}
|
||||
}
|
||||
foreach (var slot in hotbarSlots) slot?.UpdateSlotUI();
|
||||
|
||||
// Скрыть инвентарь по умолчанию
|
||||
if (inventoryPanel != null)
|
||||
inventoryPanel.SetActive(false);
|
||||
|
||||
// Убедимся что события существуют
|
||||
if (InventoryEvents.Instance == null)
|
||||
// Подписка на ввод
|
||||
if (PlayerInput.Instance != null)
|
||||
{
|
||||
var eventsGO = new GameObject("InventoryEvents");
|
||||
eventsGO.AddComponent<InventoryEvents>();
|
||||
PlayerInput.Instance.OnToggleInventory += ToggleInventory;
|
||||
PlayerInput.Instance.OnDropPressed += DropSelectedItem;
|
||||
PlayerInput.Instance.OnHotbarSelect += SelectHotbarSlot;
|
||||
}
|
||||
else
|
||||
{
|
||||
Debug.LogWarning("[InventoryManager] PlayerInput not found. Run Tools > Setup Complete Scene first.");
|
||||
}
|
||||
|
||||
// Попробуем загрузить сохранённый инвентарь
|
||||
// Загрузить сохранённый инвентарь (слоты уже существуют)
|
||||
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.OnDropPressed += DropSelectedItem;
|
||||
PlayerInput.Instance.OnHotbarSelect += SelectHotbarSlot;
|
||||
}
|
||||
|
||||
|
||||
@@ -135,14 +117,18 @@ public class InventoryManager : MonoBehaviour
|
||||
|
||||
if (!wasActive)
|
||||
{
|
||||
// Открытие инвентаря
|
||||
Cursor.lockState = CursorLockMode.None;
|
||||
Cursor.visible = true;
|
||||
InventoryEvents.Instance?.OnInventoryOpened?.Invoke();
|
||||
if (PlayerInput.Instance != null)
|
||||
PlayerInput.Instance.Enabled = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Закрытие инвентаря
|
||||
Cursor.lockState = CursorLockMode.Locked;
|
||||
Cursor.visible = false;
|
||||
InventoryEvents.Instance?.OnInventoryClosed?.Invoke();
|
||||
if (PlayerInput.Instance != null)
|
||||
PlayerInput.Instance.Enabled = true;
|
||||
@@ -559,8 +545,10 @@ public class InventoryManager : MonoBehaviour
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Сохранить инвентарь в файл (Application.persistentDataPath)
|
||||
/// Сохранить инвентарь в файл (Application.persistentDataPath).
|
||||
/// Доступно через правый клик на компоненте в Inspector во время Play Mode.
|
||||
/// </summary>
|
||||
[ContextMenu("Save Inventory")]
|
||||
public void SaveToFile()
|
||||
{
|
||||
try
|
||||
@@ -577,8 +565,11 @@ public class InventoryManager : MonoBehaviour
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Загрузить инвентарь из файла (если есть)
|
||||
/// Загрузить инвентарь из файла (если есть).
|
||||
/// Вызывается из InventoryUIBuilder после создания слотов.
|
||||
/// Доступно через правый клик на компоненте в Inspector во время Play Mode.
|
||||
/// </summary>
|
||||
[ContextMenu("Load Inventory")]
|
||||
public void LoadFromFile()
|
||||
{
|
||||
try
|
||||
|
||||
@@ -1,302 +1,133 @@
|
||||
using UnityEngine;
|
||||
using UnityEditor;
|
||||
using UnityEngine.UI;
|
||||
using UnityEngine.EventSystems;
|
||||
using TMPro;
|
||||
|
||||
public class InventorySceneSetup
|
||||
/// <summary>
|
||||
/// Tools > Setup Complete Scene — создаёт всё до запуска игры (editor-time).
|
||||
/// Canvas инвентаря помещается внутрь Player.
|
||||
/// InventoryManager получает все ссылки сразу.
|
||||
/// </summary>
|
||||
public static class InventorySceneSetup
|
||||
{
|
||||
[MenuItem("Tools/Create Player")]
|
||||
public static void CreatePlayer()
|
||||
[MenuItem("Tools/Setup Complete Scene")]
|
||||
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 cc = go.AddComponent<CharacterController>();
|
||||
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;
|
||||
var ch = go.AddComponent<charecter>();
|
||||
ch.walkSpeed = 5f;
|
||||
ch.runSpeed = 9f;
|
||||
ch.crouchSpeed = 2.5f;
|
||||
ch.jumpHeight = 1.5f;
|
||||
ch.gravity = -9.81f;
|
||||
|
||||
GameObject body = GameObject.CreatePrimitive(PrimitiveType.Capsule);
|
||||
// Визуальная капсула
|
||||
var body = GameObject.CreatePrimitive(PrimitiveType.Capsule);
|
||||
body.name = "Body";
|
||||
body.transform.SetParent(go.transform);
|
||||
body.transform.localPosition = Vector3.zero;
|
||||
GameObject.Destroy(body.GetComponent<Collider>());
|
||||
body.transform.SetParent(go.transform, false);
|
||||
Object.DestroyImmediate(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);
|
||||
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);
|
||||
var cam = camObj.AddComponent<Camera>();
|
||||
cam.tag = "MainCamera";
|
||||
var cam = camObj.AddComponent<Camera>();
|
||||
cam.tag = "MainCamera";
|
||||
cam.nearClipPlane = 0.05f;
|
||||
|
||||
var existingCam = GameObject.FindGameObjectWithTag("MainCamera");
|
||||
if (existingCam != null && existingCam != camObj)
|
||||
{
|
||||
GameObject.Destroy(existingCam);
|
||||
}
|
||||
var oldCam = GameObject.FindWithTag("MainCamera");
|
||||
if (oldCam != null && oldCam != camObj)
|
||||
Object.DestroyImmediate(oldCam);
|
||||
|
||||
go.tag = "Player";
|
||||
go.transform.position = new Vector3(0, 2, -5);
|
||||
|
||||
Selection.activeGameObject = go;
|
||||
Debug.Log("[Tools] Создан игрок!");
|
||||
return go;
|
||||
}
|
||||
|
||||
[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;
|
||||
|
||||
/// <summary>
|
||||
/// Создаёт UI инвентаря программно с использованием TextMeshPro
|
||||
/// Создаёт UI инвентаря программно.
|
||||
/// Вызывается ТОЛЬКО из редакторных инструментов (InventorySceneSetup, PlayerBuilderTool).
|
||||
/// Никакого runtime-создания: Start() отсутствует.
|
||||
/// </summary>
|
||||
public class InventoryUIBuilder : MonoBehaviour
|
||||
{
|
||||
@@ -22,138 +24,113 @@ public class InventoryUIBuilder : MonoBehaviour
|
||||
[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 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")]
|
||||
public RectTransform inventoryPanelRect;
|
||||
public RectTransform hotbarPanelRect;
|
||||
public Canvas inventoryCanvas;
|
||||
|
||||
void Start()
|
||||
{
|
||||
// Проверяем, не запущен ли уже BuildInventoryUI
|
||||
if (InventoryManager.Instance != null &&
|
||||
InventoryManager.Instance.slots != null &&
|
||||
InventoryManager.Instance.slots.Length > 0)
|
||||
{
|
||||
Debug.Log("[InventoryUIBuilder] UI already built, skipping");
|
||||
return;
|
||||
}
|
||||
// Созданные слоты — читаются редакторным инструментом после BuildInventoryUI()
|
||||
[SerializeField] private Slot[] _inventorySlots;
|
||||
[SerializeField] private Slot[] _hotbarSlots;
|
||||
|
||||
BuildInventoryUI();
|
||||
}
|
||||
public Slot[] GetInventorySlots() => _inventorySlots;
|
||||
public Slot[] GetHotbarSlots() => _hotbarSlots;
|
||||
|
||||
// ── Построение UI ────────────────────────────────────────────────────────
|
||||
|
||||
public void BuildInventoryUI()
|
||||
{
|
||||
// Создаём или получаем Canvas
|
||||
// Получаем или добавляем Canvas
|
||||
var canvas = GetComponent<Canvas>();
|
||||
if (canvas == null)
|
||||
{
|
||||
canvas = gameObject.AddComponent<Canvas>();
|
||||
canvas.renderMode = RenderMode.ScreenSpaceOverlay;
|
||||
canvas.renderMode = RenderMode.ScreenSpaceOverlay;
|
||||
canvas.sortingOrder = 100;
|
||||
gameObject.AddComponent<GraphicRaycaster>();
|
||||
}
|
||||
inventoryCanvas = canvas;
|
||||
|
||||
// Настраиваем EventSystem если нет
|
||||
if (FindObjectOfType<TMPro.TMP_InputField>() != null || FindObjectsOfType<TMPro.TextMeshProUGUI>().Length > 0)
|
||||
{
|
||||
// EventSystem уже есть
|
||||
}
|
||||
|
||||
// Создаём панель инвентаря
|
||||
// Панель инвентаря
|
||||
GameObject inventoryPanel = CreatePanel("InventoryPanel", transform, inventoryPanelColor);
|
||||
inventoryPanelRect = inventoryPanel.GetComponent<RectTransform>();
|
||||
|
||||
float inventoryWidth = inventoryCols * (slotSize + slotSpacing) + inventoryPadding * 2;
|
||||
float inventoryHeight = inventoryRows * (slotSize + slotSpacing) + inventoryPadding * 2 + 40; // +40 для заголовка
|
||||
float inventoryWidth = inventoryCols * (slotSize + slotSpacing) + inventoryPadding * 2;
|
||||
float inventoryHeight = inventoryRows * (slotSize + slotSpacing) + inventoryPadding * 2 + 40;
|
||||
|
||||
inventoryPanelRect.anchorMin = new Vector2(0.5f, 0.5f);
|
||||
inventoryPanelRect.anchorMax = new Vector2(0.5f, 0.5f);
|
||||
inventoryPanelRect.pivot = new Vector2(0.5f, 0.5f);
|
||||
inventoryPanelRect.anchorMin = new Vector2(0.5f, 0.5f);
|
||||
inventoryPanelRect.anchorMax = new Vector2(0.5f, 0.5f);
|
||||
inventoryPanelRect.pivot = new Vector2(0.5f, 0.5f);
|
||||
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));
|
||||
|
||||
// Сетка инвентаря (4x9 = 36 слотов)
|
||||
float gridHeight = inventoryRows * (slotSize + slotSpacing);
|
||||
var inventoryGrid = CreateGrid(
|
||||
inventoryPanel.transform,
|
||||
"InventoryGrid",
|
||||
inventoryCols,
|
||||
inventoryRows,
|
||||
slotSize,
|
||||
slotSpacing,
|
||||
new Vector2(inventoryPadding, inventoryPadding + 30)
|
||||
);
|
||||
InventoryManager.Instance.slots = CreateSlots(inventoryGrid, "InventorySlot_", 0, inventoryCols * inventoryRows);
|
||||
inventoryPanel.transform, "InventoryGrid",
|
||||
inventoryCols, inventoryRows,
|
||||
slotSize, slotSpacing,
|
||||
new Vector2(inventoryPadding, inventoryPadding + 30));
|
||||
|
||||
// Создаём хотбар
|
||||
_inventorySlots = CreateSlots(inventoryGrid, "InventorySlot_", 0, inventoryCols * inventoryRows);
|
||||
|
||||
// Хотбар
|
||||
GameObject hotbarPanel = CreatePanel("HotbarPanel", transform, hotbarPanelColor);
|
||||
hotbarPanelRect = hotbarPanel.GetComponent<RectTransform>();
|
||||
|
||||
float hotbarWidth = hotbarSlots * (slotSize + slotSpacing) + hotbarPadding * 2;
|
||||
|
||||
hotbarPanelRect.anchorMin = new Vector2(0.5f, 0f);
|
||||
hotbarPanelRect.anchorMax = new Vector2(0.5f, 0f);
|
||||
hotbarPanelRect.pivot = new Vector2(0.5f, 0f);
|
||||
hotbarPanelRect.anchorMin = new Vector2(0.5f, 0f);
|
||||
hotbarPanelRect.anchorMax = new Vector2(0.5f, 0f);
|
||||
hotbarPanelRect.pivot = new Vector2(0.5f, 0f);
|
||||
hotbarPanelRect.anchoredPosition = new Vector2(0, 15);
|
||||
hotbarPanelRect.sizeDelta = new Vector2(hotbarWidth, slotSize + hotbarPadding * 2);
|
||||
hotbarPanelRect.sizeDelta = new Vector2(hotbarWidth, slotSize + hotbarPadding * 2);
|
||||
|
||||
var hotbarGrid = CreateGrid(
|
||||
hotbarPanel.transform,
|
||||
"HotbarGrid",
|
||||
hotbarSlots,
|
||||
1,
|
||||
slotSize,
|
||||
slotSpacing,
|
||||
new Vector2(hotbarPadding, hotbarPadding)
|
||||
);
|
||||
InventoryManager.Instance.hotbarSlots = CreateSlots(hotbarGrid, "HotbarSlot_", 0, hotbarSlots);
|
||||
hotbarPanel.transform, "HotbarGrid",
|
||||
hotbarSlots, 1,
|
||||
slotSize, slotSpacing,
|
||||
new Vector2(hotbarPadding, hotbarPadding));
|
||||
|
||||
// Настраиваем InventoryManager
|
||||
InventoryManager.Instance.inventoryPanel = inventoryPanel;
|
||||
InventoryManager.Instance.inventoryCanvas = inventoryCanvas;
|
||||
_hotbarSlots = CreateSlots(hotbarGrid, "HotbarSlot_", 0, hotbarSlots);
|
||||
|
||||
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 panel = new GameObject(name);
|
||||
var panel = new GameObject(name);
|
||||
panel.transform.SetParent(parent, false);
|
||||
|
||||
var rect = panel.AddComponent<RectTransform>();
|
||||
panel.AddComponent<RectTransform>();
|
||||
panel.AddComponent<Image>().color = color;
|
||||
|
||||
return panel;
|
||||
}
|
||||
|
||||
void CreateTitle(Transform parent, string text, Vector2 position)
|
||||
{
|
||||
GameObject titleObj = new GameObject("Title");
|
||||
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.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);
|
||||
rect.sizeDelta = new Vector2(-20, 30);
|
||||
|
||||
var tmp = titleObj.AddComponent<TextMeshProUGUI>();
|
||||
tmp.text = text;
|
||||
tmp.fontSize = 18;
|
||||
tmp.text = text;
|
||||
tmp.fontSize = 18;
|
||||
tmp.alignment = TextAlignmentOptions.Center;
|
||||
tmp.color = Color.white;
|
||||
tmp.color = Color.white;
|
||||
}
|
||||
|
||||
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);
|
||||
|
||||
var rect = gridObj.AddComponent<RectTransform>();
|
||||
@@ -163,13 +140,13 @@ public class InventoryUIBuilder : MonoBehaviour
|
||||
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.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;
|
||||
grid.padding = new RectOffset(0, 0, 0, 0);
|
||||
grid.padding = new RectOffset(0, 0, 0, 0);
|
||||
|
||||
return gridObj.transform;
|
||||
}
|
||||
@@ -180,22 +157,21 @@ public class InventoryUIBuilder : MonoBehaviour
|
||||
|
||||
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);
|
||||
|
||||
var rect = slotObj.AddComponent<RectTransform>();
|
||||
rect.sizeDelta = new Vector2(slotSize, slotSize);
|
||||
|
||||
// Background
|
||||
var bg = slotObj.AddComponent<Image>();
|
||||
bg.color = slotEmptyColor;
|
||||
|
||||
// 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);
|
||||
var iconRect = iconObj.AddComponent<RectTransform>();
|
||||
iconRect.anchorMin = Vector2.zero;
|
||||
@@ -206,41 +182,37 @@ public class InventoryUIBuilder : MonoBehaviour
|
||||
slot.iconImage.preserveAspect = true;
|
||||
slot.iconImage.enabled = false;
|
||||
|
||||
// Amount panel
|
||||
GameObject amountObj = new GameObject("AmountPanel");
|
||||
// Количество
|
||||
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.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);
|
||||
amountRect.sizeDelta = new Vector2(22, 22);
|
||||
slot.amountPanel = amountObj;
|
||||
|
||||
var amountBg = amountObj.AddComponent<Image>();
|
||||
amountBg.color = new Color(0, 0, 0, 0.7f);
|
||||
amountObj.AddComponent<Image>().color = new Color(0, 0, 0, 0.7f);
|
||||
|
||||
GameObject amountTextObj = new GameObject("Text");
|
||||
var amountTextObj = new GameObject("Text");
|
||||
amountTextObj.transform.SetParent(amountObj.transform, false);
|
||||
var amountTextRect = amountTextObj.AddComponent<RectTransform>();
|
||||
amountTextRect.anchorMin = Vector2.zero;
|
||||
amountTextRect.anchorMax = Vector2.one;
|
||||
slot.amountText = amountTextObj.AddComponent<TextMeshProUGUI>();
|
||||
slot.amountText.fontSize = 14;
|
||||
slot.amountText.alignment = TextAlignmentOptions.Right;
|
||||
slot.amountText.color = Color.white;
|
||||
slot.amountText.fontStyle = FontStyles.Bold;
|
||||
slot.amountText = amountTextObj.AddComponent<TextMeshProUGUI>();
|
||||
slot.amountText.fontSize = 14;
|
||||
slot.amountText.alignment = TextAlignmentOptions.Right;
|
||||
slot.amountText.color = Color.white;
|
||||
slot.amountText.fontStyle = FontStyles.Bold;
|
||||
|
||||
// Применяем настройки через сеттер
|
||||
slot.amountPanel.SetActive(false);
|
||||
slot.slotBackground = bg;
|
||||
|
||||
// Drag & Drop
|
||||
var dragDrop = slotObj.AddComponent<InventoryDragDrop>();
|
||||
dragDrop.slot = slot;
|
||||
dragDrop.slot = slot;
|
||||
dragDrop.slotIndex = slot.slotIndex;
|
||||
|
||||
// Подписка на события слота
|
||||
slot.OnSlotClicked += OnSlotClicked;
|
||||
|
||||
slots[i] = slot;
|
||||
@@ -249,43 +221,38 @@ public class InventoryUIBuilder : MonoBehaviour
|
||||
return slots;
|
||||
}
|
||||
|
||||
// ── Выделение слота (runtime) ─────────────────────────────────────────────
|
||||
|
||||
private int _selectedSlot = -1;
|
||||
|
||||
private void OnSlotClicked(Slot slot)
|
||||
{
|
||||
// Снимаем выделение с предыдущего
|
||||
if (_selectedSlot >= 0 && _selectedSlot < InventoryManager.Instance.slots.Length)
|
||||
{
|
||||
InventoryManager.Instance.slots[_selectedSlot].SetSelected(false);
|
||||
}
|
||||
if (_selectedSlot >= 0 && _inventorySlots != null && _selectedSlot < _inventorySlots.Length)
|
||||
_inventorySlots[_selectedSlot].SetSelected(false);
|
||||
|
||||
// Выделяем новый
|
||||
slot.SetSelected(true);
|
||||
_selectedSlot = slot.slotIndex;
|
||||
|
||||
Debug.Log($"[UI] Selected slot: {_selectedSlot} - {slot.GetItem()?.itemName ?? "Empty"}");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Пересоздать UI (например, при изменении настроек)
|
||||
/// </summary>
|
||||
// ── Утилиты ───────────────────────────────────────────────────────────────
|
||||
|
||||
public void Rebuild()
|
||||
{
|
||||
// Удаляем старые панели
|
||||
if (inventoryPanelRect != null)
|
||||
Destroy(inventoryPanelRect.gameObject);
|
||||
if (hotbarPanelRect != null)
|
||||
Destroy(hotbarPanelRect.gameObject);
|
||||
|
||||
_inventorySlots = null;
|
||||
_hotbarSlots = null;
|
||||
BuildInventoryUI();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Показать/скрыть инвентарь
|
||||
/// </summary>
|
||||
public void ToggleInventory(bool show)
|
||||
{
|
||||
if (inventoryPanelRect != null)
|
||||
inventoryPanelRect.gameObject.SetActive(show);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,30 +1,33 @@
|
||||
using UnityEngine;
|
||||
using UnityEngine.UI;
|
||||
using UnityEditor;
|
||||
using TMPro;
|
||||
|
||||
/// <summary>
|
||||
/// Инструмент создания предметов.
|
||||
/// Tools > Item Builder
|
||||
/// </summary>
|
||||
public class ItemBuilderTool : EditorWindow
|
||||
{
|
||||
// Основные данные
|
||||
private string itemName = "NewItem";
|
||||
private string itemId = "";
|
||||
private string description = "";
|
||||
private ItemType itemType = ItemType.Material;
|
||||
private string itemName = "NewItem";
|
||||
private string itemId = "";
|
||||
private string description = "";
|
||||
private ItemType itemType = ItemType.Material;
|
||||
|
||||
// Визуал
|
||||
private GameObject modelPrefab;
|
||||
private Sprite icon;
|
||||
private Color previewColor = Color.gray;
|
||||
private Sprite icon;
|
||||
private Color previewColor = Color.gray;
|
||||
|
||||
// Свойства
|
||||
private int maxStack = 64;
|
||||
private int value = 1;
|
||||
private float weight = 1f;
|
||||
private bool isDroppable = true;
|
||||
private bool isStackable = true;
|
||||
private int maxStack = 64;
|
||||
private int value = 1;
|
||||
private float weight = 1f;
|
||||
private bool isDroppable = true;
|
||||
private bool isStackable = true;
|
||||
|
||||
// Префаб
|
||||
private GameObject worldItemPrefab;
|
||||
// Pickup
|
||||
private float interactRange = 2.5f;
|
||||
|
||||
[MenuItem("Tools/Item Builder")]
|
||||
public static void ShowWindow()
|
||||
@@ -38,67 +41,59 @@ public class ItemBuilderTool : EditorWindow
|
||||
|
||||
// Основные данные
|
||||
GUILayout.Label("Основное", EditorStyles.miniBoldLabel);
|
||||
itemName = EditorGUILayout.TextField("Название", itemName);
|
||||
itemId = EditorGUILayout.TextField("ID", itemId);
|
||||
itemName = EditorGUILayout.TextField("Название", itemName);
|
||||
itemId = EditorGUILayout.TextField("ID (оставь пустым для GUID)", itemId);
|
||||
description = EditorGUILayout.TextField("Описание", description);
|
||||
itemType = (ItemType)EditorGUILayout.EnumPopup("Тип предмета", itemType);
|
||||
itemType = (ItemType)EditorGUILayout.EnumPopup("Тип предмета", itemType);
|
||||
|
||||
GUILayout.Space(10);
|
||||
|
||||
// Визуал
|
||||
GUILayout.Label("Визуал", EditorStyles.miniBoldLabel);
|
||||
modelPrefab = (GameObject)EditorGUILayout.ObjectField("3D модель", modelPrefab, typeof(GameObject), false);
|
||||
icon = (Sprite)EditorGUILayout.ObjectField("Иконка", icon, typeof(Sprite), false);
|
||||
modelPrefab = (GameObject)EditorGUILayout.ObjectField("3D модель (префаб)", modelPrefab, typeof(GameObject), false);
|
||||
icon = (Sprite)EditorGUILayout.ObjectField("Иконка", icon, typeof(Sprite), false);
|
||||
|
||||
if (icon == null)
|
||||
{
|
||||
previewColor = EditorGUILayout.ColorField("Цвет иконки", previewColor);
|
||||
}
|
||||
previewColor = EditorGUILayout.ColorField("Цвет иконки (заглушка)", previewColor);
|
||||
|
||||
GUILayout.Space(10);
|
||||
|
||||
// Свойства
|
||||
GUILayout.Label("Свойства", EditorStyles.miniBoldLabel);
|
||||
maxStack = EditorGUILayout.IntField("Макс. стек", maxStack);
|
||||
value = EditorGUILayout.IntField("Цена", value);
|
||||
weight = EditorGUILayout.FloatField("Вес", weight);
|
||||
maxStack = EditorGUILayout.IntField("Макс. стек", maxStack);
|
||||
value = EditorGUILayout.IntField("Цена", value);
|
||||
weight = EditorGUILayout.FloatField("Вес", weight);
|
||||
isDroppable = EditorGUILayout.Toggle("Можно выбросить", isDroppable);
|
||||
isStackable = EditorGUILayout.Toggle("Стек", isStackable);
|
||||
isStackable = EditorGUILayout.Toggle("Стекируемый", isStackable);
|
||||
|
||||
GUILayout.Space(10);
|
||||
|
||||
// Префаб
|
||||
GUILayout.Label("Префаб предмета в мире", EditorStyles.miniBoldLabel);
|
||||
worldItemPrefab = (GameObject)EditorGUILayout.ObjectField("WorldItem Prefab", worldItemPrefab, typeof(GameObject), false);
|
||||
GUILayout.Label("Подбор", EditorStyles.miniBoldLabel);
|
||||
interactRange = EditorGUILayout.FloatField("Дальность подбора (E)", interactRange);
|
||||
|
||||
GUILayout.Space(20);
|
||||
|
||||
// Кнопки
|
||||
GUI.color = Color.green;
|
||||
if (GUILayout.Button("Создать ItemData"))
|
||||
{
|
||||
if (GUILayout.Button("Создать ItemData (ScriptableObject)"))
|
||||
CreateItemData();
|
||||
}
|
||||
|
||||
GUI.color = Color.cyan;
|
||||
if (GUILayout.Button("Создать WorldItem в сцене"))
|
||||
{
|
||||
CreateWorldItem();
|
||||
}
|
||||
|
||||
GUI.color = Color.yellow;
|
||||
if (GUILayout.Button("Создать префаб"))
|
||||
{
|
||||
if (GUILayout.Button("Создать WorldItem как префаб"))
|
||||
CreateItemPrefab();
|
||||
}
|
||||
|
||||
GUI.color = Color.white;
|
||||
|
||||
GUILayout.Space(10);
|
||||
EditorGUILayout.HelpBox(
|
||||
"1. Заполните данные предмета\n" +
|
||||
"2. Назначьте модель и иконку\n" +
|
||||
"3. Создайте ItemData или префаб",
|
||||
"Подбор предметов — только по кнопке E (авто-pickup при касании убран намеренно).\n" +
|
||||
"1. Заполните данные → Создайте ItemData\n" +
|
||||
"2. Назначьте ItemData в InventoryManager.itemDatabase\n" +
|
||||
"3. Создайте WorldItem для размещения предметов на сцене",
|
||||
MessageType.Info);
|
||||
}
|
||||
|
||||
@@ -112,105 +107,101 @@ public class ItemBuilderTool : EditorWindow
|
||||
|
||||
var item = ScriptableObject.CreateInstance<ItemData>();
|
||||
|
||||
item.id = string.IsNullOrEmpty(itemId) ? GUID.Generate().ToString() : itemId;
|
||||
item.itemName = itemName;
|
||||
item.id = string.IsNullOrEmpty(itemId) ? System.Guid.NewGuid().ToString() : itemId;
|
||||
item.itemName = itemName;
|
||||
item.description = description;
|
||||
item.type = itemType;
|
||||
item.type = itemType;
|
||||
item.modelPrefab = modelPrefab;
|
||||
item.icon = icon != null ? icon : CreatePlaceholderIcon();
|
||||
item.maxStack = maxStack;
|
||||
item.value = value;
|
||||
item.weight = weight;
|
||||
item.icon = icon != null ? icon : CreatePlaceholderIcon();
|
||||
item.maxStack = maxStack;
|
||||
item.value = value;
|
||||
item.weight = weight;
|
||||
item.isDroppable = isDroppable;
|
||||
item.isStackable = isStackable;
|
||||
|
||||
// Сохраняем
|
||||
string path = $"Assets/Inventory/Items/{itemName}.asset";
|
||||
string folder = System.IO.Path.GetDirectoryName(path);
|
||||
string folder = "Assets/Inventory/Items";
|
||||
if (!System.IO.Directory.Exists(folder))
|
||||
{
|
||||
System.IO.Directory.CreateDirectory(folder);
|
||||
}
|
||||
|
||||
string path = $"{folder}/{itemName}.asset";
|
||||
AssetDatabase.CreateAsset(item, path);
|
||||
AssetDatabase.SaveAssets();
|
||||
|
||||
Selection.activeObject = item;
|
||||
Debug.Log($"[ItemBuilder] Создан: {itemName}");
|
||||
Debug.Log($"[ItemBuilder] Создан: {itemName} → {path}");
|
||||
}
|
||||
|
||||
void CreateWorldItem()
|
||||
{
|
||||
if (modelPrefab == null)
|
||||
var itemGO = new GameObject(itemName);
|
||||
|
||||
// Визуал
|
||||
GameObject visual;
|
||||
if (modelPrefab != null)
|
||||
{
|
||||
// Создаём простой визуал
|
||||
var itemGO = new GameObject(itemName);
|
||||
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;
|
||||
DestroyImmediate(visual.GetComponent<Collider>());
|
||||
|
||||
var worldItem = itemGO.AddComponent<WorldItem>();
|
||||
var col = itemGO.AddComponent<SphereCollider>();
|
||||
col.radius = 0.5f;
|
||||
col.isTrigger = true;
|
||||
|
||||
itemGO.transform.position = Vector3.zero;
|
||||
Selection.activeGameObject = itemGO;
|
||||
visual = (GameObject)PrefabUtility.InstantiatePrefab(modelPrefab, itemGO.transform);
|
||||
}
|
||||
else
|
||||
{
|
||||
var itemGO = Instantiate(modelPrefab);
|
||||
itemGO.name = itemName;
|
||||
itemGO.AddComponent<WorldItem>();
|
||||
itemGO.transform.position = Vector3.zero;
|
||||
Selection.activeGameObject = itemGO;
|
||||
visual = GameObject.CreatePrimitive(PrimitiveType.Cube);
|
||||
visual.transform.SetParent(itemGO.transform, false);
|
||||
visual.transform.localScale = Vector3.one * 0.3f;
|
||||
DestroyImmediate(visual.GetComponent<Collider>());
|
||||
}
|
||||
visual.name = "Visual";
|
||||
visual.transform.localPosition = Vector3.zero;
|
||||
|
||||
// WorldItem компонент
|
||||
var worldItem = itemGO.AddComponent<WorldItem>();
|
||||
worldItem.interactRange = interactRange;
|
||||
|
||||
// Trigger-коллайдер для OverlapSphere (не для авто-pickup!)
|
||||
var col = itemGO.AddComponent<SphereCollider>();
|
||||
col.radius = 0.5f;
|
||||
col.isTrigger = true;
|
||||
|
||||
itemGO.transform.position = Vector3.zero;
|
||||
Selection.activeGameObject = itemGO;
|
||||
Debug.Log($"[ItemBuilder] Создан WorldItem: {itemName}");
|
||||
}
|
||||
|
||||
void CreateItemPrefab()
|
||||
{
|
||||
string path = EditorUtility.SaveFilePanelInProject(
|
||||
"Сохранить префаб",
|
||||
"Сохранить WorldItem префаб",
|
||||
itemName,
|
||||
"prefab",
|
||||
"Выберите место");
|
||||
"Выберите место сохранения");
|
||||
|
||||
if (string.IsNullOrEmpty(path)) return;
|
||||
|
||||
GameObject prefab;
|
||||
var prefabGO = new GameObject(itemName);
|
||||
|
||||
// Визуал
|
||||
GameObject visual;
|
||||
if (modelPrefab != null)
|
||||
{
|
||||
prefab = Instantiate(modelPrefab);
|
||||
prefab.name = itemName;
|
||||
visual = (GameObject)PrefabUtility.InstantiatePrefab(modelPrefab, prefabGO.transform);
|
||||
}
|
||||
else
|
||||
{
|
||||
prefab = new GameObject(itemName);
|
||||
var visual = GameObject.CreatePrimitive(PrimitiveType.Cube);
|
||||
visual.name = "Visual";
|
||||
visual.transform.SetParent(prefab.transform);
|
||||
visual.transform.localPosition = Vector3.zero;
|
||||
visual = GameObject.CreatePrimitive(PrimitiveType.Cube);
|
||||
visual.transform.SetParent(prefabGO.transform, false);
|
||||
visual.transform.localScale = Vector3.one * 0.3f;
|
||||
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>();
|
||||
if (col == null)
|
||||
{
|
||||
var sphere = prefab.AddComponent<SphereCollider>();
|
||||
sphere.radius = 0.5f;
|
||||
sphere.isTrigger = true;
|
||||
}
|
||||
var col = prefabGO.AddComponent<SphereCollider>();
|
||||
col.radius = 0.5f;
|
||||
col.isTrigger = true;
|
||||
|
||||
GameObject savedPrefab = PrefabUtility.SaveAsPrefabAsset(prefab, path);
|
||||
DestroyImmediate(prefab);
|
||||
GameObject savedPrefab = PrefabUtility.SaveAsPrefabAsset(prefabGO, path);
|
||||
DestroyImmediate(prefabGO);
|
||||
|
||||
Selection.activeObject = savedPrefab;
|
||||
Debug.Log($"[ItemBuilder] Префаб сохранён: {path}");
|
||||
@@ -218,14 +209,12 @@ public class ItemBuilderTool : EditorWindow
|
||||
|
||||
Sprite CreatePlaceholderIcon()
|
||||
{
|
||||
var tex = new Texture2D(64, 64);
|
||||
var tex = new Texture2D(64, 64);
|
||||
var colors = new Color[64 * 64];
|
||||
for (int i = 0; i < colors.Length; i++)
|
||||
{
|
||||
colors[i] = previewColor;
|
||||
}
|
||||
tex.SetPixels(colors);
|
||||
tex.Apply();
|
||||
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;
|
||||
#endif
|
||||
|
||||
/// <summary>
|
||||
/// Компонент для генерации ItemData ScriptableObject из настроек в Inspector.
|
||||
/// Добавьте на GameObject, заполните поля и нажмите "Generate ItemData" в Inspector.
|
||||
/// </summary>
|
||||
public class ItemGenerator : MonoBehaviour
|
||||
{
|
||||
[Header("Item Template")]
|
||||
@@ -26,27 +30,25 @@ public class ItemGenerator : MonoBehaviour
|
||||
public ItemData GenerateItemData()
|
||||
{
|
||||
if (string.IsNullOrEmpty(itemId))
|
||||
{
|
||||
itemId = System.Guid.NewGuid().ToString();
|
||||
}
|
||||
|
||||
var itemData = ScriptableObject.CreateInstance<ItemData>();
|
||||
itemData.id = itemId;
|
||||
itemData.itemName = itemName;
|
||||
itemData.id = itemId;
|
||||
itemData.itemName = itemName;
|
||||
itemData.description = description;
|
||||
itemData.type = itemType;
|
||||
itemData.type = itemType;
|
||||
itemData.modelPrefab = modelPrefab;
|
||||
itemData.icon = icon;
|
||||
itemData.maxStack = maxStack;
|
||||
itemData.icon = icon;
|
||||
itemData.maxStack = maxStack;
|
||||
itemData.isCraftable = isCraftable;
|
||||
|
||||
if (isCraftable && craftIngredients != null && craftIngredients.Length > 0)
|
||||
{
|
||||
itemData.craftingRecipe = new ItemData.CraftingRecipe
|
||||
{
|
||||
ingredients = craftIngredients,
|
||||
amounts = craftAmounts,
|
||||
resultId = craftResultId,
|
||||
ingredients = craftIngredients,
|
||||
amounts = craftAmounts,
|
||||
resultId = craftResultId,
|
||||
resultAmount = craftResultAmount
|
||||
};
|
||||
}
|
||||
@@ -57,187 +59,15 @@ public class ItemGenerator : MonoBehaviour
|
||||
public static List<ItemData> GenerateAll(List<ItemGenerator> generators)
|
||||
{
|
||||
var items = new List<ItemData>();
|
||||
foreach (var generator in generators)
|
||||
foreach (var gen in generators)
|
||||
{
|
||||
if (generator != null)
|
||||
{
|
||||
items.Add(generator.GenerateItemData());
|
||||
}
|
||||
if (gen != null)
|
||||
items.Add(gen.GenerateItemData());
|
||||
}
|
||||
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
|
||||
[CustomEditor(typeof(ItemGenerator))]
|
||||
public class ItemGeneratorEditor : Editor
|
||||
@@ -246,17 +76,23 @@ public class ItemGeneratorEditor : Editor
|
||||
{
|
||||
base.OnInspectorGUI();
|
||||
|
||||
GUILayout.Space(8);
|
||||
|
||||
if (GUILayout.Button("Generate ItemData"))
|
||||
{
|
||||
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.SaveAssets();
|
||||
|
||||
Debug.Log($"Created item: {itemData.itemName} at {path}");
|
||||
Debug.Log($"[ItemGenerator] Created item: {itemData.itemName} at {path}");
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
|
||||
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.UI;
|
||||
using UnityEditor;
|
||||
using UnityEditor.Animations;
|
||||
using UnityEngine.UI;
|
||||
using UnityEngine.EventSystems;
|
||||
|
||||
/// <summary>
|
||||
/// Инструмент создания полного игрока с опциональным инвентарём.
|
||||
/// Tools > Player Builder
|
||||
/// </summary>
|
||||
public class PlayerBuilderTool : EditorWindow
|
||||
{
|
||||
// Модель
|
||||
// ── Модель ────────────────────────────────────────────────────────────────
|
||||
private GameObject characterModel;
|
||||
private Transform headBone;
|
||||
private Transform headBone;
|
||||
private Transform handBone;
|
||||
|
||||
// Параметры движения
|
||||
private float walkSpeed = 5f;
|
||||
private float runSpeed = 9f;
|
||||
// ── Параметры движения ────────────────────────────────────────────────────
|
||||
private float walkSpeed = 5f;
|
||||
private float runSpeed = 9f;
|
||||
private float crouchSpeed = 2.5f;
|
||||
private float jumpHeight = 1.5f;
|
||||
private float gravity = -9.81f;
|
||||
private float jumpHeight = 1.5f;
|
||||
private float gravity = -9.81f;
|
||||
|
||||
// Коллайдер
|
||||
private float height = 1.8f;
|
||||
private float radius = 0.5f;
|
||||
// ── Коллайдер ─────────────────────────────────────────────────────────────
|
||||
private float height = 1.8f;
|
||||
private float radius = 0.5f;
|
||||
private float centerY = 0.9f;
|
||||
|
||||
// Камера
|
||||
private bool addCamera = true;
|
||||
// ── Камера ────────────────────────────────────────────────────────────────
|
||||
private bool addCamera = true;
|
||||
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 walkClip;
|
||||
private AnimationClip runClip;
|
||||
@@ -33,9 +47,8 @@ public class PlayerBuilderTool : EditorWindow
|
||||
private AnimationClip crouchIdleClip;
|
||||
private AnimationClip crouchWalkClip;
|
||||
|
||||
// Аниматор контроллер
|
||||
private AnimatorController animatorController;
|
||||
private bool createAnimatorController = true;
|
||||
// ── Scroll ────────────────────────────────────────────────────────────────
|
||||
private Vector2 _scroll;
|
||||
|
||||
[MenuItem("Tools/Player Builder")]
|
||||
public static void ShowWindow()
|
||||
@@ -45,97 +58,121 @@ public class PlayerBuilderTool : EditorWindow
|
||||
|
||||
void OnGUI()
|
||||
{
|
||||
GUILayout.Label("Настройки персонажа", EditorStyles.boldLabel);
|
||||
_scroll = EditorGUILayout.BeginScrollView(_scroll);
|
||||
|
||||
// Секция модели
|
||||
GUILayout.Label("Конструктор Персонажа", EditorStyles.boldLabel);
|
||||
|
||||
// ── Секция модели ─────────────────────────────────────────────────────
|
||||
GUILayout.Space(6);
|
||||
GUILayout.Label("Модель", EditorStyles.miniBoldLabel);
|
||||
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);
|
||||
walkSpeed = EditorGUILayout.FloatField("Скорость ходьбы", walkSpeed);
|
||||
runSpeed = EditorGUILayout.FloatField("Скорость бега", runSpeed);
|
||||
crouchSpeed = EditorGUILayout.FloatField("Скорость краулинга", crouchSpeed);
|
||||
jumpHeight = EditorGUILayout.FloatField("Высота прыжка", jumpHeight);
|
||||
gravity = EditorGUILayout.FloatField("Гравитация", gravity);
|
||||
walkSpeed = EditorGUILayout.FloatField("Скорость ходьбы", walkSpeed);
|
||||
runSpeed = EditorGUILayout.FloatField("Скорость бега", runSpeed);
|
||||
crouchSpeed = EditorGUILayout.FloatField("Скорость присядки", crouchSpeed);
|
||||
jumpHeight = EditorGUILayout.FloatField("Высота прыжка", jumpHeight);
|
||||
gravity = EditorGUILayout.FloatField("Гравитация", gravity);
|
||||
|
||||
GUILayout.Space(10);
|
||||
|
||||
// Секция коллайдера
|
||||
GUILayout.Label("Коллайдер", EditorStyles.miniBoldLabel);
|
||||
height = EditorGUILayout.FloatField("Высота", height);
|
||||
radius = EditorGUILayout.FloatField("Радиус", radius);
|
||||
// ── Коллайдер ─────────────────────────────────────────────────────────
|
||||
GUILayout.Space(6);
|
||||
GUILayout.Label("Коллайдер CharacterController", EditorStyles.miniBoldLabel);
|
||||
height = EditorGUILayout.FloatField("Высота", height);
|
||||
radius = EditorGUILayout.FloatField("Радиус", radius);
|
||||
centerY = EditorGUILayout.FloatField("Центр Y", centerY);
|
||||
|
||||
GUILayout.Space(10);
|
||||
|
||||
// Секция камеры
|
||||
// ── Камера ────────────────────────────────────────────────────────────
|
||||
GUILayout.Space(6);
|
||||
GUILayout.Label("Камера", EditorStyles.miniBoldLabel);
|
||||
addCamera = EditorGUILayout.Toggle("Добавить камеру", addCamera);
|
||||
addCamera = EditorGUILayout.Toggle("Добавить камеру", addCamera);
|
||||
if (addCamera)
|
||||
{
|
||||
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.Label("Анимации", EditorStyles.miniBoldLabel);
|
||||
createAnimatorController = EditorGUILayout.Toggle("Создать контроллер", createAnimatorController);
|
||||
idleClip = (AnimationClip)EditorGUILayout.ObjectField("Idle", idleClip, typeof(AnimationClip), false);
|
||||
walkClip = (AnimationClip)EditorGUILayout.ObjectField("Walk", walkClip, typeof(AnimationClip), false);
|
||||
runClip = (AnimationClip)EditorGUILayout.ObjectField("Run", runClip, typeof(AnimationClip), false);
|
||||
jumpClip = (AnimationClip)EditorGUILayout.ObjectField("Jump", jumpClip, typeof(AnimationClip), false);
|
||||
// ── Анимации ──────────────────────────────────────────────────────────
|
||||
GUILayout.Space(6);
|
||||
GUILayout.Label("Анимации (опционально)", EditorStyles.miniBoldLabel);
|
||||
idleClip = (AnimationClip)EditorGUILayout.ObjectField("Idle", idleClip, typeof(AnimationClip), false);
|
||||
walkClip = (AnimationClip)EditorGUILayout.ObjectField("Walk", walkClip, typeof(AnimationClip), false);
|
||||
runClip = (AnimationClip)EditorGUILayout.ObjectField("Run", runClip, typeof(AnimationClip), false);
|
||||
jumpClip = (AnimationClip)EditorGUILayout.ObjectField("Jump", jumpClip, typeof(AnimationClip), false);
|
||||
crouchIdleClip = (AnimationClip)EditorGUILayout.ObjectField("Crouch Idle", crouchIdleClip, 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);
|
||||
|
||||
// Кнопки действий
|
||||
// ── Кнопки ────────────────────────────────────────────────────────────
|
||||
GUI.color = Color.green;
|
||||
if (GUILayout.Button("Создать в сцене"))
|
||||
{
|
||||
if (GUILayout.Button("Создать игрока" + (includeInventory ? " + Инвентарь" : "")))
|
||||
BuildPlayer("Player");
|
||||
}
|
||||
|
||||
GUI.color = Color.yellow;
|
||||
if (GUILayout.Button("Создать тестового игрока (капсула)"))
|
||||
BuildTestPlayer();
|
||||
|
||||
GUI.color = Color.cyan;
|
||||
if (GUILayout.Button("Сохранить как префаб"))
|
||||
{
|
||||
SaveAsPrefab();
|
||||
}
|
||||
|
||||
GUI.color = Color.yellow;
|
||||
if (GUILayout.Button("Создать с тестовой моделью (капсула)"))
|
||||
{
|
||||
BuildTestPlayer();
|
||||
}
|
||||
|
||||
GUI.color = Color.white;
|
||||
|
||||
GUILayout.Space(10);
|
||||
EditorGUILayout.HelpBox(
|
||||
"1. Назначьте модель персонажа\n" +
|
||||
"2. Назначьте анимации (опционально)\n" +
|
||||
"3. Настройте параметры\n" +
|
||||
"4. Нажмите 'Создать в сцене'",
|
||||
"1. Назначьте модель персонажа (опционально)\n" +
|
||||
"2. Укажите кость головы и кость руки\n" +
|
||||
"3. Назначьте PlayerControls.inputactions\n" +
|
||||
"4. Нажмите 'Создать игрока'",
|
||||
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
|
||||
var cc = player.AddComponent<CharacterController>();
|
||||
@@ -145,31 +182,27 @@ public class PlayerBuilderTool : EditorWindow
|
||||
|
||||
// Скрипт персонажа
|
||||
var character = player.AddComponent<charecter>();
|
||||
character.walkSpeed = walkSpeed;
|
||||
character.runSpeed = runSpeed;
|
||||
character.walkSpeed = walkSpeed;
|
||||
character.runSpeed = runSpeed;
|
||||
character.crouchSpeed = crouchSpeed;
|
||||
character.jumpHeight = jumpHeight;
|
||||
character.gravity = gravity;
|
||||
character.jumpHeight = jumpHeight;
|
||||
character.gravity = gravity;
|
||||
|
||||
// Модель
|
||||
GameObject model = null;
|
||||
Transform resolvedHead = headBone;
|
||||
Transform resolvedHand = handBone;
|
||||
|
||||
if (characterModel != null)
|
||||
{
|
||||
model = Instantiate(characterModel, player.transform);
|
||||
var model = (GameObject)PrefabUtility.InstantiatePrefab(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 (resolvedHead == null)
|
||||
resolvedHead = FindChildBone(model.transform, "head") ?? FindChildBone(model.transform, "Head");
|
||||
if (resolvedHand == null)
|
||||
resolvedHand = FindChildBone(model.transform, "hand_r") ?? FindChildBone(model.transform, "RightHand");
|
||||
|
||||
//Animator
|
||||
var modelAnimator = model.GetComponent<Animator>();
|
||||
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");
|
||||
headObj.transform.SetParent(model != null ? model.transform : player.transform);
|
||||
var headObj = new GameObject("HeadPoint");
|
||||
headObj.transform.SetParent(player.transform);
|
||||
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");
|
||||
cameraObj.transform.SetParent(character.head);
|
||||
cameraObj.transform.localPosition = new Vector3(0, 0.1f, 0);
|
||||
var camObj = new GameObject("PlayerCamera");
|
||||
camObj.transform.SetParent(resolvedHead);
|
||||
camObj.transform.localPosition = new Vector3(0, 0.1f, 0);
|
||||
var cam = camObj.AddComponent<Camera>();
|
||||
cam.tag = "MainCamera";
|
||||
cam.nearClipPlane = 0.05f;
|
||||
|
||||
var cam = cameraObj.AddComponent<Camera>();
|
||||
cam.tag = "MainCamera";
|
||||
cam.nearClipPlane = 0.1f;
|
||||
|
||||
// Удалить старую
|
||||
var oldCam = GameObject.FindWithTag("MainCamera");
|
||||
if (oldCam != null && oldCam != cameraObj)
|
||||
{
|
||||
if (oldCam != null && oldCam != camObj)
|
||||
DestroyImmediate(oldCam);
|
||||
}
|
||||
}
|
||||
|
||||
// Тег
|
||||
player.tag = "Player";
|
||||
// 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.transform.position = new Vector3(0, 2, -5);
|
||||
|
||||
Selection.activeGameObject = player;
|
||||
Debug.Log($"[PlayerBuilder] Создан: {playerName}");
|
||||
// Инвентарь
|
||||
if (includeInventory)
|
||||
SetupInventoryForPlayer(player);
|
||||
|
||||
return player;
|
||||
}
|
||||
|
||||
void SaveAsPrefab()
|
||||
void BuildPlayer(string name)
|
||||
{
|
||||
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}");
|
||||
var player = BuildPlayerGO(name);
|
||||
Selection.activeGameObject = player;
|
||||
Debug.Log($"[PlayerBuilder] Создан: {name}");
|
||||
}
|
||||
|
||||
void BuildTestPlayer()
|
||||
{
|
||||
var savedModel = characterModel;
|
||||
characterModel = null;
|
||||
headBone = null;
|
||||
BuildPlayer("TestPlayer");
|
||||
var player = BuildPlayerGO("TestPlayer");
|
||||
characterModel = savedModel;
|
||||
|
||||
GameObject player = Selection.activeGameObject;
|
||||
if (player == null) return;
|
||||
|
||||
// Создаём визуальную часть
|
||||
GameObject body = GameObject.CreatePrimitive(PrimitiveType.Capsule);
|
||||
// Визуальная капсула
|
||||
var body = GameObject.CreatePrimitive(PrimitiveType.Capsule);
|
||||
body.name = "Body";
|
||||
body.transform.SetParent(player.transform);
|
||||
body.transform.localPosition = Vector3.zero;
|
||||
body.transform.SetParent(player.transform, false);
|
||||
body.transform.localPosition = new Vector3(0, centerY, 0);
|
||||
body.transform.localScale = new Vector3(radius * 2, height / 2f, radius * 2);
|
||||
DestroyImmediate(body.GetComponent<Collider>());
|
||||
|
||||
GameObject head = new GameObject("Head");
|
||||
head.transform.SetParent(player.transform);
|
||||
head.transform.localPosition = new Vector3(0, centerY + 0.2f, 0);
|
||||
|
||||
var character = player.GetComponent<charecter>();
|
||||
if (character != null)
|
||||
{
|
||||
character.head = head.transform;
|
||||
}
|
||||
|
||||
if (addCamera)
|
||||
{
|
||||
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 oldCam = GameObject.FindWithTag("MainCamera");
|
||||
if (oldCam != null && oldCam != camObj)
|
||||
{
|
||||
DestroyImmediate(oldCam);
|
||||
}
|
||||
}
|
||||
|
||||
Debug.Log("[PlayerBuilder] Создан тестовый игрок");
|
||||
Selection.activeGameObject = player;
|
||||
Debug.Log("[PlayerBuilder] Создан тестовый игрок (капсула)");
|
||||
}
|
||||
|
||||
void SaveAsPrefab()
|
||||
{
|
||||
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}");
|
||||
}
|
||||
|
||||
// ── Создание инвентаря ────────────────────────────────────────────────────
|
||||
|
||||
void SetupInventoryForPlayer(GameObject player)
|
||||
{
|
||||
// EventSystem
|
||||
if (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>();
|
||||
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)
|
||||
{
|
||||
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)
|
||||
{
|
||||
var result = FindChildBone(child, boneName);
|
||||
@@ -300,4 +361,4 @@ public class PlayerBuilderTool : EditorWindow
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,29 +1,51 @@
|
||||
using UnityEngine;
|
||||
using System;
|
||||
using UnityEngine.InputSystem;
|
||||
|
||||
/// <summary>
|
||||
/// Централизованный ввод на основе New Input System.
|
||||
/// Singleton, DontDestroyOnLoad.
|
||||
/// Биндинги сохраняются в PlayerPrefs автоматически при изменении.
|
||||
/// </summary>
|
||||
public class PlayerInput : MonoBehaviour
|
||||
{
|
||||
public static PlayerInput Instance { get; private set; }
|
||||
|
||||
// Continuous axes
|
||||
public float MouseX { get; private set; }
|
||||
public float MouseY { get; private set; }
|
||||
public float Horizontal { get; private set; }
|
||||
public float Vertical { get; private set; }
|
||||
// ── Ссылка на InputActionAsset ────────────────────────────────────────────
|
||||
[Tooltip("Назначьте Assets/Input/PlayerControls.inputactions")]
|
||||
public InputActionAsset actions;
|
||||
|
||||
// Continuous states
|
||||
public bool Crouch { get; private set; }
|
||||
public bool Run { get; private set; }
|
||||
// ── Непрерывные значения ──────────────────────────────────────────────────
|
||||
public Vector2 MoveInput { get; private set; }
|
||||
public Vector2 LookInput { get; private set; }
|
||||
public bool Crouch { get; private set; }
|
||||
public bool Run { get; private set; }
|
||||
|
||||
// Events for discrete actions
|
||||
public event Action OnToggleInventory;
|
||||
public event Action OnDropPressed;
|
||||
public event Action OnPickupPressed;
|
||||
public event Action OnJumpPressed;
|
||||
public event Action<int> OnHotbarSelect;
|
||||
// ── Дискретные события ────────────────────────────────────────────────────
|
||||
public event Action OnToggleInventory;
|
||||
public event Action OnDropPressed;
|
||||
public event Action OnPickupPressed;
|
||||
public event Action OnJumpPressed;
|
||||
public event Action<int> OnHotbarSelect;
|
||||
|
||||
public bool Enabled { get; set; } = true;
|
||||
// ── Включение/выключение 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()
|
||||
{
|
||||
if (Instance == null)
|
||||
@@ -34,46 +56,116 @@ public class PlayerInput : MonoBehaviour
|
||||
else
|
||||
{
|
||||
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()
|
||||
{
|
||||
// Always allow toggle inventory (Tab/Escape) even when input is disabled
|
||||
if (Input.GetKeyDown(KeyCode.Tab) || Input.GetKeyDown(KeyCode.Escape))
|
||||
OnToggleInventory?.Invoke();
|
||||
if (_gameplayMap == null || !_gameplayMap.enabled) return;
|
||||
|
||||
if (!Enabled) return;
|
||||
|
||||
// Axes
|
||||
MouseX = Input.GetAxis("Mouse X");
|
||||
MouseY = Input.GetAxis("Mouse Y");
|
||||
Horizontal = Input.GetAxisRaw("Horizontal");
|
||||
Vertical = Input.GetAxisRaw("Vertical");
|
||||
|
||||
// Continuous keys
|
||||
Crouch = Input.GetKey(KeyCode.C);
|
||||
Run = Input.GetKey(KeyCode.LeftShift);
|
||||
|
||||
// Discrete actions
|
||||
if (Input.GetButtonDown("Jump"))
|
||||
OnJumpPressed?.Invoke();
|
||||
|
||||
if (Input.GetKeyDown(KeyCode.Tab))
|
||||
OnToggleInventory?.Invoke();
|
||||
|
||||
if (Input.GetKeyDown(KeyCode.Q))
|
||||
OnDropPressed?.Invoke();
|
||||
|
||||
if (Input.GetKeyDown(KeyCode.E))
|
||||
OnPickupPressed?.Invoke();
|
||||
|
||||
for (int i = 0; i < 9; i++)
|
||||
{
|
||||
if (Input.GetKeyDown(KeyCode.Alpha1 + i))
|
||||
{
|
||||
OnHotbarSelect?.Invoke(i);
|
||||
}
|
||||
}
|
||||
MoveInput = _gameplayMap["Move"].ReadValue<Vector2>();
|
||||
LookInput = _gameplayMap["Look"].ReadValue<Vector2>();
|
||||
Crouch = _gameplayMap["Crouch"].IsPressed();
|
||||
Run = _gameplayMap["Run"].IsPressed();
|
||||
}
|
||||
|
||||
// ── Сохранение/загрузка биндингов ────────────────────────────────────────
|
||||
|
||||
[ContextMenu("Save Bindings")]
|
||||
public void SaveBindings()
|
||||
{
|
||||
if (actions == null) return;
|
||||
PlayerPrefs.SetString(BINDINGS_PREF_KEY, actions.SaveBindingOverridesAsJson());
|
||||
PlayerPrefs.Save();
|
||||
Debug.Log("[PlayerInput] Биндинги сохранены");
|
||||
}
|
||||
|
||||
[ContextMenu("Reset Bindings to Defaults")]
|
||||
public void ResetBindings()
|
||||
{
|
||||
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;
|
||||
}
|
||||
|
||||
@@ -4,11 +4,11 @@ using UnityEngine;
|
||||
public class charecter : MonoBehaviour
|
||||
{
|
||||
[Header("Movement")]
|
||||
public float walkSpeed = 5f;
|
||||
public float runSpeed = 9f;
|
||||
public float walkSpeed = 5f;
|
||||
public float runSpeed = 9f;
|
||||
public float crouchSpeed = 2.5f;
|
||||
public float jumpHeight = 1.5f;
|
||||
public float gravity = -9.81f;
|
||||
public float jumpHeight = 1.5f;
|
||||
public float gravity = -9.81f;
|
||||
|
||||
[Header("References")]
|
||||
[Tooltip("Head BONE of the character.")]
|
||||
@@ -46,20 +46,21 @@ public class charecter : MonoBehaviour
|
||||
_cc = GetComponent<CharacterController>();
|
||||
_anim = GetComponentInChildren<Animator>();
|
||||
Cursor.lockState = CursorLockMode.Locked;
|
||||
Cursor.visible = false;
|
||||
|
||||
_bodyYaw = transform.eulerAngles.y;
|
||||
_headYaw = _bodyYaw;
|
||||
_headBindPose = head.localRotation;
|
||||
_headBindPose = head != null ? head.localRotation : Quaternion.identity;
|
||||
|
||||
// Ensure PlayerInput exists and subscribe to events
|
||||
// Убедиться что PlayerInput существует
|
||||
if (PlayerInput.Instance == null)
|
||||
{
|
||||
var go = new GameObject("PlayerInput");
|
||||
go.AddComponent<PlayerInput>();
|
||||
}
|
||||
|
||||
PlayerInput.Instance.OnPickupPressed += () => TryPickupNearbyItem();
|
||||
PlayerInput.Instance.OnJumpPressed += () => { _jumpRequested = true; };
|
||||
PlayerInput.Instance.OnPickupPressed += TryPickupNearbyItem;
|
||||
PlayerInput.Instance.OnJumpPressed += () => { _jumpRequested = true; };
|
||||
}
|
||||
|
||||
void Update()
|
||||
@@ -68,55 +69,35 @@ public class charecter : MonoBehaviour
|
||||
HandleMovement();
|
||||
}
|
||||
|
||||
// ── Item Pickup ───────────────────────────────────────────────────────────
|
||||
void HandlePickup()
|
||||
void LateUpdate()
|
||||
{
|
||||
// Input moved to PlayerInput events
|
||||
ApplyRotations();
|
||||
}
|
||||
|
||||
// ── Item Pickup ───────────────────────────────────────────────────────────
|
||||
void TryPickupNearbyItem()
|
||||
{
|
||||
float pickupRadius = 2.5f;
|
||||
Collider[] colliders = Physics.OverlapSphere(transform.position, pickupRadius);
|
||||
|
||||
Debug.Log($"[Pickup] Checking {colliders.Length} colliders in radius {pickupRadius}");
|
||||
|
||||
WorldItem closestItem = null;
|
||||
float closestDist = float.MaxValue;
|
||||
|
||||
foreach (var col in colliders)
|
||||
{
|
||||
var worldItem = col.GetComponent<WorldItem>();
|
||||
if (worldItem != null)
|
||||
if (worldItem == null) continue;
|
||||
|
||||
float dist = Vector3.Distance(transform.position, worldItem.transform.position);
|
||||
if (dist < closestDist && dist <= worldItem.interactRange)
|
||||
{
|
||||
float dist = Vector3.Distance(transform.position, worldItem.transform.position);
|
||||
Debug.Log($"[Pickup] Found WorldItem: {worldItem.itemData?.itemName ?? "null"} at dist {dist}");
|
||||
if (dist < closestDist)
|
||||
{
|
||||
closestDist = dist;
|
||||
closestItem = worldItem;
|
||||
}
|
||||
closestDist = dist;
|
||||
closestItem = worldItem;
|
||||
}
|
||||
}
|
||||
|
||||
if (closestItem != null)
|
||||
{
|
||||
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();
|
||||
closestItem.TryPickupByButton();
|
||||
}
|
||||
|
||||
// ── Mouse look ────────────────────────────────────────────────────────────
|
||||
@@ -125,21 +106,21 @@ public class charecter : MonoBehaviour
|
||||
var input = PlayerInput.Instance;
|
||||
if (input != null)
|
||||
{
|
||||
_headYaw += input.MouseX * mouseSensitivity;
|
||||
_pitch -= input.MouseY * mouseSensitivity;
|
||||
_headYaw += input.LookInput.x * mouseSensitivity;
|
||||
_pitch -= input.LookInput.y * mouseSensitivity;
|
||||
}
|
||||
_pitch = Mathf.Clamp(_pitch, -maxPitch, maxPitch);
|
||||
_pitch = Mathf.Clamp(_pitch, -maxPitch, maxPitch);
|
||||
}
|
||||
|
||||
// ── Movement ──────────────────────────────────────────────────────────────
|
||||
void HandleMovement()
|
||||
{
|
||||
var input = PlayerInput.Instance;
|
||||
float h = input != null ? input.Horizontal : Input.GetAxisRaw("Horizontal");
|
||||
float v = input != null ? input.Vertical : Input.GetAxisRaw("Vertical");
|
||||
float h = input != null ? input.MoveInput.x : 0f;
|
||||
float v = input != null ? input.MoveInput.y : 0f;
|
||||
|
||||
bool isCrouching = input != null ? input.Crouch : Input.GetKey(KeyCode.C);
|
||||
bool isRunning = input != null ? input.Run && !isCrouching : Input.GetKey(KeyCode.LeftShift) && !isCrouching;
|
||||
bool isCrouching = input != null && input.Crouch;
|
||||
bool isRunning = input != null && input.Run && !isCrouching;
|
||||
bool isMoving = (h * h + v * v) > 0.01f;
|
||||
|
||||
float speed = isCrouching ? crouchSpeed : isRunning ? runSpeed : walkSpeed;
|
||||
@@ -148,7 +129,7 @@ public class charecter : MonoBehaviour
|
||||
if (isMoving)
|
||||
_bodyYaw = Mathf.MoveTowardsAngle(_bodyYaw, _headYaw, bodyAlignSpeed * Time.deltaTime);
|
||||
|
||||
// Head-drag
|
||||
// Head-drag clamp
|
||||
float offset = Mathf.DeltaAngle(_bodyYaw, _headYaw);
|
||||
float clampedOffset = Mathf.Clamp(offset, -maxHeadYaw, maxHeadYaw);
|
||||
_bodyYaw += offset - clampedOffset;
|
||||
@@ -176,12 +157,11 @@ public class charecter : MonoBehaviour
|
||||
moveDir.y = _verticalVelocity;
|
||||
_cc.Move(moveDir * speed * Time.deltaTime);
|
||||
|
||||
// Animator params
|
||||
// Animator
|
||||
if (_anim != null)
|
||||
{
|
||||
// Speed: 0 = idle, 0.5 = walk, 1 = run
|
||||
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 (HashIsCrouching, isCrouching);
|
||||
_anim.SetBool (HashIsGrounded, _cc.isGrounded);
|
||||
@@ -193,10 +173,11 @@ public class charecter : MonoBehaviour
|
||||
{
|
||||
transform.rotation = Quaternion.Euler(0f, _bodyYaw, 0f);
|
||||
|
||||
float headOffset = Mathf.DeltaAngle(_bodyYaw, _headYaw);
|
||||
Quaternion yawRot = Quaternion.Euler(0f, headOffset, 0f);
|
||||
Quaternion pitchRot = Quaternion.Euler(_pitch, 0f, 0f);
|
||||
head.localRotation = _headBindPose * yawRot * pitchRot;
|
||||
if (head == null) return;
|
||||
|
||||
float headOffset = Mathf.DeltaAngle(_bodyYaw, _headYaw);
|
||||
Quaternion yawRot = Quaternion.Euler(0f, headOffset, 0f);
|
||||
Quaternion pitchRot = Quaternion.Euler(_pitch, 0f, 0f);
|
||||
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
|
||||
|
||||
This is a Unity game project with two major systems:
|
||||
1. **Character Controller** - First/third-person movement with animations
|
||||
2. **Inventory System** - Full inventory with hotbar, drag-drop, crafting, and item generation
|
||||
Unity game project (no CLI build commands — use the Unity Editor). Two major systems:
|
||||
1. **Character Controller** — first/third-person movement with animations
|
||||
2. **Inventory System** — hotbar, drag-drop, crafting, world items, save/load
|
||||
|
||||
## Controls
|
||||
|
||||
- **Movement**: WASD
|
||||
- **Look**: Mouse
|
||||
- **Run**: Left Shift
|
||||
- **Crouch**: C
|
||||
- **Jump**: Space
|
||||
- **Toggle Inventory**: Tab
|
||||
- **Close Inventory**: Escape
|
||||
- **Hotbar Selection**: 1-9 keys
|
||||
- **Drop Item**: Q
|
||||
|
||||
## Key Files and Structure
|
||||
|
||||
### 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
|
||||
| Action | Key |
|
||||
|---|---|
|
||||
| Move | WASD |
|
||||
| Look | Mouse |
|
||||
| Run | Left Shift |
|
||||
| Crouch | C |
|
||||
| Jump | Space |
|
||||
| Pickup | E |
|
||||
| Toggle Inventory | Tab |
|
||||
| Close Inventory | Escape |
|
||||
| Hotbar Select | 1–9 |
|
||||
| Drop Item | Q |
|
||||
|
||||
## Architecture
|
||||
|
||||
### Character Controller Design
|
||||
- Uses Unity's CharacterController component for collision
|
||||
- Head-body separation: body rotates toward look direction, head can offset within limits
|
||||
- Animator parameters use `Animator.StringToHash` for performance (Speed, IsMoving, IsCrouching, IsGrounded, Jump)
|
||||
- Physics-based jumping: `v = sqrt(jumpHeight * -2 * gravity)`
|
||||
- All movement is framerate-independent with `Time.deltaTime`
|
||||
### Input Layer — `PlayerInput` (singleton, DontDestroyOnLoad)
|
||||
All input is centralised in `Assets/charecter-controller/scripts/PlayerInput.cs`. It exposes:
|
||||
- Continuous properties: `MouseX`, `MouseY`, `Horizontal`, `Vertical`, `Crouch`, `Run`
|
||||
- C# events: `OnJumpPressed`, `OnPickupPressed`, `OnToggleInventory`, `OnDropPressed`, `OnHotbarSelect`
|
||||
- `Enabled` flag — set to `false` when the inventory is open to block gameplay input
|
||||
|
||||
### Inventory Architecture
|
||||
- **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
|
||||
Both `charecter.cs` and `InventoryManager.cs` subscribe to `PlayerInput.Instance` events in `Start()`. Never read `Input.*` directly in new code — go through `PlayerInput`.
|
||||
|
||||
### Inventory Flow
|
||||
1. Items added via `AddItem(itemId, amount)` - tries existing stacks first, then empty slots
|
||||
2. Removed via `RemoveItem(itemId, amount)` - returns true if successful
|
||||
3. Hotbar selection via `SelectHotbarSlot(index)` - updates visual selection
|
||||
4. Item dropped via `DropSelectedItem()` - spawns world object via InventoryItemFactory
|
||||
5. JSON serialization via `ExportToJson()` / `ImportFromJson()`
|
||||
### Character Controller — `charecter.cs`
|
||||
- Requires `CharacterController` component
|
||||
- Head-bone / body separation: body yaw tracks camera yaw when moving; head offset is clamped to `±maxHeadYaw`
|
||||
- Bone rotations applied in `LateUpdate` via `ApplyRotations()`
|
||||
- Animator hashes cached as `static readonly int` fields; animator Speed param: 0 = idle, 0.5 = walk, 1 = run
|
||||
- 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
|
||||
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.ide.rider": "3.0.39",
|
||||
"com.unity.ide.visualstudio": "2.0.27",
|
||||
"com.unity.inputsystem": "1.19.0",
|
||||
"com.unity.multiplayer.center": "1.0.1",
|
||||
"com.unity.purchasing": "4.15.0",
|
||||
"com.unity.test-framework": "1.6.0",
|
||||
|
||||
@@ -75,6 +75,15 @@
|
||||
},
|
||||
"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": {
|
||||
"version": "1.0.1",
|
||||
"depth": 0,
|
||||
|
||||
@@ -5,5 +5,5 @@ EditorBuildSettings:
|
||||
m_ObjectHideFlags: 0
|
||||
serializedVersion: 2
|
||||
m_Scenes: []
|
||||
m_configObjects: {}
|
||||
m_UseUCBPForAssetBundles: 0
|
||||
m_configObjects:
|
||||
com.unity.input.settings.actions: {fileID: -944628639613478452, guid: 7d782555f7e02f84ca2502d52361f19a, type: 3}
|
||||
|
||||
@@ -41,7 +41,6 @@ PlayerSettings:
|
||||
height: 1
|
||||
m_SplashScreenLogos: []
|
||||
m_VirtualRealitySplashScreen: {fileID: 0}
|
||||
m_HolographicTrackingLossScreen: {fileID: 0}
|
||||
defaultScreenWidth: 1920
|
||||
defaultScreenHeight: 1080
|
||||
defaultScreenWidthWeb: 960
|
||||
@@ -148,12 +147,10 @@ PlayerSettings:
|
||||
preloadedAssets: []
|
||||
metroInputSource: 0
|
||||
wsaTransparentSwapchain: 0
|
||||
m_HolographicPauseOnTrackingLoss: 1
|
||||
xboxOneDisableKinectGpuReservation: 1
|
||||
xboxOneEnable7thCore: 1
|
||||
vrSettings:
|
||||
enable360StereoCapture: 0
|
||||
isWsaHolographicRemotingEnabled: 0
|
||||
enableFrameTimingStats: 0
|
||||
enableOpenGLProfilerGPURecorders: 1
|
||||
allowHDRDisplaySupport: 0
|
||||
@@ -762,8 +759,9 @@ PlayerSettings:
|
||||
qnxGraphicConfPath:
|
||||
apiCompatibilityLevel: 6
|
||||
captureStartupLogs: {}
|
||||
activeInputHandler: 0
|
||||
activeInputHandler: 2
|
||||
windowsGamepadBackendHint: 0
|
||||
enableDirectStorage: 0
|
||||
cloudProjectId:
|
||||
framebufferDepthMemorylessMode: 0
|
||||
qualitySettingsNames: []
|
||||
|
||||
Reference in New Issue
Block a user