diff --git a/.claude/settings.local.json b/.claude/settings.local.json
index 8983121..e8e2a68 100644
--- a/.claude/settings.local.json
+++ b/.claude/settings.local.json
@@ -2,7 +2,9 @@
"permissions": {
"allow": [
"WebSearch",
- "WebFetch(domain:docs.unity3d.com)"
+ "WebFetch(domain:docs.unity3d.com)",
+ "Bash(grep -l \"3009578ee03d9ed46a97978c08168eee\" \"c:/Users/jze9/Documents/unity/my-project/Assets/Blocks/texturs/\"*.meta)",
+ "Bash(grep -l \"640e614afcdf0cc42ae02e2b478ae512\" \"c:/Users/jze9/Documents/unity/my-project/Assets/Blocks/texturs/\"*.meta)"
]
}
}
diff --git a/Assets/Blocks/Blok.obj b/Assets/Blocks/Blok.obj
new file mode 100644
index 0000000..7d9eb0d
--- /dev/null
+++ b/Assets/Blocks/Blok.obj
@@ -0,0 +1,50 @@
+# Blender 5.1.1
+# www.blender.org
+mtllib Blok.mtl
+o Cube
+v 1.000000 1.000000 -1.000000
+v 1.000000 -1.000000 -1.000000
+v 1.000000 1.000000 1.000000
+v 1.000000 -1.000000 1.000000
+v -1.000000 1.000000 -1.000000
+v -1.000000 -1.000000 -1.000000
+v -1.000000 1.000000 1.000000
+v -1.000000 -1.000000 1.000000
+vn -0.0000 1.0000 -0.0000
+vn -0.0000 -0.0000 1.0000
+vn -1.0000 -0.0000 -0.0000
+vn -0.0000 -1.0000 -0.0000
+vn 1.0000 -0.0000 -0.0000
+vn -0.0000 -0.0000 -1.0000
+vt 0.498423 0.501818
+vt 0.498423 0.998602
+vt 0.001023 0.998602
+vt 0.001023 0.501818
+vt 0.999046 0.500959
+vt 0.999046 0.999078
+vt 0.500927 0.999078
+vt 0.500927 0.500959
+vt 0.999042 0.500940
+vt 0.999042 0.999059
+vt 0.500923 0.999059
+vt 0.500923 0.500940
+vt 0.498289 0.001223
+vt 0.498289 0.499608
+vt 0.001369 0.499608
+vt 0.001369 0.001223
+vt 0.999051 0.500945
+vt 0.999051 0.999064
+vt 0.500931 0.999064
+vt 0.500931 0.500944
+vt 0.999044 0.500954
+vt 0.999043 0.999074
+vt 0.500924 0.999074
+vt 0.500924 0.500954
+s 0
+usemtl Material0
+f 1/1/1 5/2/1 7/3/1 3/4/1
+f 4/5/2 3/6/2 7/7/2 8/8/2
+f 8/9/3 7/10/3 5/11/3 6/12/3
+f 6/13/4 2/14/4 4/15/4 8/16/4
+f 2/17/5 1/18/5 3/19/5 4/20/5
+f 6/21/6 5/22/6 1/23/6 2/24/6
diff --git a/Assets/Blocks/Blok.obj.meta b/Assets/Blocks/Blok.obj.meta
new file mode 100644
index 0000000..62c48b6
--- /dev/null
+++ b/Assets/Blocks/Blok.obj.meta
@@ -0,0 +1,110 @@
+fileFormatVersion: 2
+guid: 9491bc8c1f13b6541bb223ae6d55788a
+ModelImporter:
+ serializedVersion: 24200
+ internalIDToNameTable: []
+ externalObjects: {}
+ materials:
+ materialImportMode: 2
+ materialName: 0
+ materialSearch: 1
+ materialLocation: 1
+ animations:
+ legacyGenerateAnimations: 4
+ bakeSimulation: 0
+ resampleCurves: 1
+ optimizeGameObjects: 0
+ removeConstantScaleCurves: 0
+ motionNodeName:
+ animationImportErrors:
+ animationImportWarnings:
+ animationRetargetingWarnings:
+ animationDoRetargetingWarnings: 0
+ importAnimatedCustomProperties: 0
+ importConstraints: 0
+ animationCompression: 1
+ animationRotationError: 0.5
+ animationPositionError: 0.5
+ animationScaleError: 0.5
+ animationWrapMode: 0
+ extraExposedTransformPaths: []
+ extraUserProperties: []
+ clipAnimations: []
+ isReadable: 0
+ meshes:
+ lODScreenPercentages: []
+ globalScale: 1
+ meshCompression: 0
+ addColliders: 0
+ useSRGBMaterialColor: 1
+ sortHierarchyByName: 1
+ importPhysicalCameras: 1
+ importVisibility: 1
+ importBlendShapes: 1
+ importCameras: 1
+ importLights: 1
+ nodeNameCollisionStrategy: 1
+ fileIdsGeneration: 2
+ swapUVChannels: 0
+ generateSecondaryUV: 0
+ useFileUnits: 1
+ keepQuads: 0
+ weldVertices: 1
+ bakeAxisConversion: 0
+ preserveHierarchy: 0
+ skinWeightsMode: 0
+ maxBonesPerVertex: 4
+ minBoneWeight: 0.001
+ optimizeBones: 1
+ generateMeshLods: 0
+ meshLodGenerationFlags: 0
+ maximumMeshLod: -1
+ meshOptimizationFlags: -1
+ indexFormat: 0
+ secondaryUVAngleDistortion: 8
+ secondaryUVAreaDistortion: 15.000001
+ secondaryUVHardAngle: 88
+ secondaryUVMarginMethod: 1
+ secondaryUVMinLightmapResolution: 40
+ secondaryUVMinObjectScale: 1
+ secondaryUVPackMargin: 4
+ useFileScale: 1
+ strictVertexDataChecks: 0
+ tangentSpace:
+ normalSmoothAngle: 60
+ normalImportMode: 0
+ tangentImportMode: 3
+ normalCalculationMode: 4
+ legacyComputeAllNormalsFromSmoothingGroupsWhenMeshHasBlendShapes: 0
+ blendShapeNormalImportMode: 1
+ normalSmoothingSource: 0
+ referencedClips: []
+ importAnimation: 1
+ humanDescription:
+ serializedVersion: 3
+ human: []
+ skeleton: []
+ armTwist: 0.5
+ foreArmTwist: 0.5
+ upperLegTwist: 0.5
+ legTwist: 0.5
+ armStretch: 0.05
+ legStretch: 0.05
+ feetSpacing: 0
+ globalScale: 1
+ rootMotionBoneName:
+ hasTranslationDoF: 0
+ hasExtraRoot: 0
+ skeletonHasParents: 1
+ lastHumanDescriptionAvatarSource: {instanceID: 0}
+ autoGenerateAvatarMappingIfUnspecified: 1
+ animationType: 2
+ humanoidOversampling: 1
+ avatarSetup: 0
+ addHumanoidExtraRootOnlyWhenUsingAvatar: 1
+ importBlendShapeDeformPercent: 1
+ remapMaterialsIfMaterialImportModeIsNone: 0
+ additionalBone: 0
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/Assets/Items/ferstitem.prefab.meta b/Assets/Blocks/Definitions.meta
similarity index 57%
rename from Assets/Items/ferstitem.prefab.meta
rename to Assets/Blocks/Definitions.meta
index 4d6ff76..b1d2f48 100644
--- a/Assets/Items/ferstitem.prefab.meta
+++ b/Assets/Blocks/Definitions.meta
@@ -1,6 +1,7 @@
fileFormatVersion: 2
-guid: 06e51a4df39df524397e91edba2a833d
-PrefabImporter:
+guid: 2caa39746acdf3e449c6ffe7b49194b0
+folderAsset: yes
+DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
diff --git a/Assets/Blocks/Definitions/tree.asset b/Assets/Blocks/Definitions/tree.asset
new file mode 100644
index 0000000..2039d77
--- /dev/null
+++ b/Assets/Blocks/Definitions/tree.asset
@@ -0,0 +1,24 @@
+%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: 0c5e75bc3cec52e44bb5bcb6687e6237, type: 3}
+ m_Name: tree
+ m_EditorClassIdentifier: Assembly-CSharp::BlockDefinition
+ blockId: 1
+ displayName: tree
+ topTexture: {fileID: 2800000, guid: 31d7c3b267ede19409f90e3eed1c1266, type: 3}
+ bottomTexture: {fileID: 2800000, guid: 31d7c3b267ede19409f90e3eed1c1266, type: 3}
+ sideTexture: {fileID: 2800000, guid: 31d7c3b267ede19409f90e3eed1c1266, type: 3}
+ linkedItem: {fileID: 11400000, guid: 131ca9b5c83edfe4d9c35a6ef4a380a5, type: 2}
+ isSolid: 1
+ topIndex: 0
+ bottomIndex: 1
+ sideIndex: 2
diff --git a/Assets/Inventory/Items/ferstitem123.asset.meta b/Assets/Blocks/Definitions/tree.asset.meta
similarity index 79%
rename from Assets/Inventory/Items/ferstitem123.asset.meta
rename to Assets/Blocks/Definitions/tree.asset.meta
index b93667b..16cc144 100644
--- a/Assets/Inventory/Items/ferstitem123.asset.meta
+++ b/Assets/Blocks/Definitions/tree.asset.meta
@@ -1,5 +1,5 @@
fileFormatVersion: 2
-guid: 5db581fdeb06daf4da37cb3d6f32b5ff
+guid: f827f1cb7a209854598b7f1ee52d32e4
NativeFormatImporter:
externalObjects: {}
mainObjectFileID: 11400000
diff --git a/Assets/Blocks/Scripts/BlockDefinition.cs b/Assets/Blocks/Scripts/BlockDefinition.cs
index 879d5cb..4718e87 100644
--- a/Assets/Blocks/Scripts/BlockDefinition.cs
+++ b/Assets/Blocks/Scripts/BlockDefinition.cs
@@ -11,10 +11,10 @@ public class BlockDefinition : ScriptableObject
public string blockId; // уникальный ID, например "grass", "dirt"
public string displayName;
- [Header("Textures (128×128)")]
- public Texture2D topTexture; // грань Y+
- public Texture2D bottomTexture; // грань Y-
- public Texture2D sideTexture; // все 4 боковых грани
+ [Header("Textures (Sprite или Texture2D)")]
+ public Sprite topTexture; // грань Y+
+ public Sprite bottomTexture; // грань Y-
+ public Sprite sideTexture; // все 4 боковых грани
[Header("Inventory Link")]
[Tooltip("ItemData с типом Block, связанная с этим блоком")]
diff --git a/Assets/Blocks/Scripts/BlockPlacer.cs b/Assets/Blocks/Scripts/BlockPlacer.cs
index 75a6569..73ec399 100644
--- a/Assets/Blocks/Scripts/BlockPlacer.cs
+++ b/Assets/Blocks/Scripts/BlockPlacer.cs
@@ -17,11 +17,12 @@ public class BlockPlacer : MonoBehaviour
public Texture2D crackTexture; // текстура трещин (grayscale)
// ── Приватное ─────────────────────────────────────────────────────────────
- Camera _cam;
- float _breakProgress;
- Vector3Int _breakingBlock = Vector3Int.one * int.MinValue; // "никакой"
- GameObject _breakOverlay;
- MeshRenderer _overlayRenderer;
+ Camera _cam;
+ float _breakProgress;
+ Vector3Int _breakingBlock = Vector3Int.one * int.MinValue;
+ GameObject _breakOverlay;
+ MeshRenderer _overlayRenderer;
+ MaterialPropertyBlock _mpb;
static readonly int PropProgress = Shader.PropertyToID("_Progress");
@@ -49,7 +50,7 @@ public class BlockPlacer : MonoBehaviour
void HandleBreak()
{
- if (!Input.GetMouseButton(0))
+ if (PlayerInput.Instance == null || !PlayerInput.Instance.BreakHeld)
{
CancelBreak();
return;
@@ -61,6 +62,7 @@ public class BlockPlacer : MonoBehaviour
return;
}
+
// Сменился ли целевой блок?
if (blockPos != _breakingBlock)
{
@@ -106,7 +108,7 @@ public class BlockPlacer : MonoBehaviour
void HandlePlace()
{
- if (!Input.GetMouseButtonDown(1)) return;
+ if (PlayerInput.Instance == null || !PlayerInput.Instance.PlacePressed) return;
if (!Raycast(out RaycastHit hit, out Vector3Int blockPos)) return;
// Ячейка, куда ставим = сосед грани которую мы смотрим
@@ -120,11 +122,7 @@ public class BlockPlacer : MonoBehaviour
if (selectedItem == null) return;
var def = BlockRegistry.Instance?.GetByItemId(selectedItem.id);
- if (def == null)
- {
- Debug.Log($"[BlockPlacer] {selectedItem.itemName} не является блоком.");
- return;
- }
+ if (def == null) return;
WorldManager.Instance.PlaceBlock(placePos, def.blockId);
@@ -154,11 +152,10 @@ public class BlockPlacer : MonoBehaviour
void UpdateOverlay(float progress)
{
if (_overlayRenderer == null) return;
- // MaterialPropertyBlock — не создаём новый экземпляр материала
- var mpb = new MaterialPropertyBlock();
- _overlayRenderer.GetPropertyBlock(mpb);
- mpb.SetFloat(PropProgress, progress);
- _overlayRenderer.SetPropertyBlock(mpb);
+ _mpb ??= new MaterialPropertyBlock();
+ _overlayRenderer.GetPropertyBlock(_mpb);
+ _mpb.SetFloat(PropProgress, progress);
+ _overlayRenderer.SetPropertyBlock(_mpb);
}
// ── Утилиты ───────────────────────────────────────────────────────────────
@@ -166,9 +163,13 @@ public class BlockPlacer : MonoBehaviour
bool Raycast(out RaycastHit hit, out Vector3Int blockPos)
{
blockPos = default;
- Ray ray = new Ray(_cam.transform.position, _cam.transform.forward);
+ Ray ray = new Ray(_cam.transform.position, _cam.transform.forward);
- if (Physics.Raycast(ray, out hit, reach, blockLayer))
+ // blockLayer == 0 означает "Nothing" в Unity LayerMask — рейкаст ни по чему не попадёт.
+ // Если слой не назначен в Inspector, бьём по всем слоям (-1 = Everything).
+ int mask = blockLayer.value == 0 ? ~0 : blockLayer.value;
+
+ if (Physics.Raycast(ray, out hit, reach, mask))
{
// hit.point лежит на грани — смещаемся чуть внутрь блока
Vector3 inner = hit.point - hit.normal * 0.01f;
diff --git a/Assets/Blocks/Scripts/BlockRegistry.cs b/Assets/Blocks/Scripts/BlockRegistry.cs
index 5713e18..ca87fc9 100644
--- a/Assets/Blocks/Scripts/BlockRegistry.cs
+++ b/Assets/Blocks/Scripts/BlockRegistry.cs
@@ -45,7 +45,14 @@ public class BlockRegistry : MonoBehaviour
// Собираем уникальные текстуры (top/bottom/side каждого блока)
// Порядок: для блока i → top=i*3, bottom=i*3+1, side=i*3+2
int layerCount = definitions.Count * 3;
- int res = 128; // разрешение должно совпадать с текстурами блоков
+
+ // Авто-определяем разрешение по первой найденной текстуре (берём из rect спрайта)
+ int res = 16;
+ foreach (var d in definitions)
+ {
+ Sprite s = d.topTexture ?? d.sideTexture ?? d.bottomTexture;
+ if (s != null) { res = (int)s.rect.width; break; }
+ }
TexArray = new Texture2DArray(res, res, layerCount,
TextureFormat.RGBA32, true, false);
@@ -100,40 +107,43 @@ public class BlockRegistry : MonoBehaviour
// ── Утилиты ───────────────────────────────────────────────────────────────
///
- /// Копирует пиксели из src в Texture2DArray на слой layerIndex.
- /// Если src null или не того размера — заполняет пурпурным (ошибка-текстура).
+ /// Копирует один спрайт (или его часть из атласа) в слой Texture2DArray.
+ /// Использует Graphics.Blit с UV offset/scale — Read/Write не нужен.
+ /// Если src null — заполняет пурпурным (ошибка-текстура).
///
- static void CopyTexture(Texture2D src, Texture2DArray dst, int layerIndex, int res)
+ static void CopyTexture(Sprite src, Texture2DArray dst, int layerIndex, int res)
{
- Color[] pixels;
-
if (src == null)
{
- // Пурпурный = "текстура не назначена"
- pixels = new Color[res * res];
+ var pixels = new Color[res * res];
for (int p = 0; p < pixels.Length; p++)
pixels[p] = (p / res + p) % 2 == 0 ? Color.magenta : Color.black;
- }
- else if (src.width != res || src.height != res)
- {
- Debug.LogWarning($"[BlockRegistry] {src.name} is {src.width}×{src.height}, expected {res}×{res}. Scaling.");
- // Простой fallback — масштабировать через RenderTexture
- var rt = RenderTexture.GetTemporary(res, res);
- Graphics.Blit(src, rt);
- var prev = RenderTexture.active;
- RenderTexture.active = rt;
- var resized = new Texture2D(res, res, TextureFormat.RGBA32, false);
- resized.ReadPixels(new Rect(0, 0, res, res), 0, 0);
- resized.Apply();
- RenderTexture.active = prev;
- RenderTexture.ReleaseTemporary(rt);
- pixels = resized.GetPixels();
- }
- else
- {
- pixels = src.GetPixels();
+ dst.SetPixels(pixels, layerIndex);
+ return;
}
- dst.SetPixels(pixels, layerIndex);
+ // Вычисляем UV offset/scale этого спрайта внутри атласа.
+ // sprite.rect — пиксельные координаты (origin = bottom-left атласа).
+ float atlasW = src.texture.width;
+ float atlasH = src.texture.height;
+ var scale = new Vector2(src.rect.width / atlasW, src.rect.height / atlasH);
+ var offset = new Vector2(src.rect.x / atlasW, src.rect.y / atlasH);
+
+ var rt = RenderTexture.GetTemporary(res, res, 0, RenderTextureFormat.ARGB32);
+ var prevFilter = src.texture.filterMode;
+ src.texture.filterMode = FilterMode.Point;
+ Graphics.Blit(src.texture, rt, scale, offset);
+ src.texture.filterMode = prevFilter;
+
+ var prev = RenderTexture.active;
+ RenderTexture.active = rt;
+ var tmp = new Texture2D(res, res, TextureFormat.RGBA32, false);
+ tmp.ReadPixels(new Rect(0, 0, res, res), 0, 0);
+ tmp.Apply();
+ RenderTexture.active = prev;
+ RenderTexture.ReleaseTemporary(rt);
+
+ dst.SetPixels(tmp.GetPixels(), layerIndex);
+ Object.Destroy(tmp);
}
}
diff --git a/Assets/Blocks/Scripts/Chunk.cs b/Assets/Blocks/Scripts/Chunk.cs
index 88fe11a..2968fd1 100644
--- a/Assets/Blocks/Scripts/Chunk.cs
+++ b/Assets/Blocks/Scripts/Chunk.cs
@@ -30,18 +30,18 @@ public class Chunk : MonoBehaviour
// Порядок по часовой стрелке, смотрим снаружи
static readonly Vector3[][] FaceVerts =
{
- // Top (Y+)
+ // Top (Y+) — нормаль (0,+1,0) ✓
new[] { new Vector3(0,1,0), new Vector3(0,1,1), new Vector3(1,1,1), new Vector3(1,1,0) },
- // Bottom (Y-)
+ // Bottom (Y-) — нормаль (0,-1,0) ✓
new[] { new Vector3(0,0,0), new Vector3(1,0,0), new Vector3(1,0,1), new Vector3(0,0,1) },
- // Front (Z+)
- new[] { new Vector3(1,0,1), new Vector3(0,0,1), new Vector3(0,1,1), new Vector3(1,1,1) },
- // Back (Z-)
- new[] { new Vector3(0,0,0), new Vector3(1,0,0), new Vector3(1,1,0), new Vector3(0,1,0) },
- // Right (X+)
- new[] { new Vector3(1,0,0), new Vector3(1,0,1), new Vector3(1,1,1), new Vector3(1,1,0) },
- // Left (X-)
- new[] { new Vector3(0,0,1), new Vector3(0,0,0), new Vector3(0,1,0), new Vector3(0,1,1) }
+ // Front (Z+) — нормаль (0,0,+1), исправлен порядок вершин
+ new[] { new Vector3(0,0,1), new Vector3(1,0,1), new Vector3(1,1,1), new Vector3(0,1,1) },
+ // Back (Z-) — нормаль (0,0,-1), исправлен порядок вершин
+ new[] { new Vector3(1,0,0), new Vector3(0,0,0), new Vector3(0,1,0), new Vector3(1,1,0) },
+ // Right (X+) — нормаль (+1,0,0), исправлен порядок вершин
+ new[] { new Vector3(1,0,1), new Vector3(1,0,0), new Vector3(1,1,0), new Vector3(1,1,1) },
+ // Left (X-) — нормаль (-1,0,0), исправлен порядок вершин
+ new[] { new Vector3(0,0,0), new Vector3(0,0,1), new Vector3(0,1,1), new Vector3(0,1,0) }
};
// UV для каждой из 4 вершин грани
@@ -63,11 +63,11 @@ public class Chunk : MonoBehaviour
_filter.sharedMesh = _mesh;
}
- public void Initialise(ChunkData data, Material chunkMaterial)
+ public void Initialise(ChunkData data, Material chunkMaterial, bool buildMesh = true)
{
Data = data;
_renderer.sharedMaterial = chunkMaterial;
- RebuildMesh();
+ if (buildMesh) RebuildMesh();
}
// ── Публичный API ─────────────────────────────────────────────────────────
@@ -92,10 +92,10 @@ public class Chunk : MonoBehaviour
{
if (Data == null) return;
- var verts = new List();
- var tris = new List();
- var uvs = new List(); // UV0: координаты на грани 0-1
- var texCoord1 = new List(); // UV1: x = индекс в Texture2DArray
+ var verts = new List();
+ var tris = new List();
+ var uvs = new List(); // UV0: координаты на грани 0-1
+ var texCoord1 = new List(); // UV1: x = texIndex, y = face brightness
for (int x = 0; x < ChunkData.SIZE; x++)
for (int y = 0; y < ChunkData.HEIGHT; y++)
@@ -114,19 +114,23 @@ public class Chunk : MonoBehaviour
// Face culling: пропускаем грань если сосед — твёрдый блок
if (HasSolidNeighbour(neighbour)) continue;
- // Индекс текстуры для этой грани
- int texIndex = f == 0 ? def.topIndex :
- f == 1 ? def.bottomIndex :
- def.sideIndex;
+ // Индекс текстуры и яркость грани (Minecraft-стиль)
+ int texIndex = f == 0 ? def.topIndex :
+ f == 1 ? def.bottomIndex :
+ def.sideIndex;
+ float bright = f == 0 ? 1.0f : // top
+ f == 1 ? 0.5f : // bottom
+ 0.8f; // sides
int baseVert = verts.Count;
var origin = new Vector3(x, y, z);
+ var faceUV = new Vector2(texIndex, bright); // одна аллокация на грань, не на вершину
for (int v = 0; v < 4; v++)
{
verts.Add(origin + FaceVerts[f][v]);
uvs.Add(FaceUVs[v]);
- texCoord1.Add(new Vector2(texIndex, 0));
+ texCoord1.Add(faceUV);
}
// Два треугольника на грань
diff --git a/Assets/Blocks/Scripts/FlatWorldGenerator.cs b/Assets/Blocks/Scripts/FlatWorldGenerator.cs
index f76a2b8..10e069a 100644
--- a/Assets/Blocks/Scripts/FlatWorldGenerator.cs
+++ b/Assets/Blocks/Scripts/FlatWorldGenerator.cs
@@ -53,6 +53,10 @@ public class FlatWorldGenerator : MonoBehaviour
WorldManager.Instance.CreateChunk(chunkPos, data);
}
+ // Перестраиваем все меши после создания всех чанков —
+ // иначе граничные грани между соседними чанками не скрываются
+ WorldManager.Instance.RebuildAllChunks();
+
Debug.Log($"[FlatWorldGenerator] Generated {chunksX * chunksZ} chunks.");
}
diff --git a/Assets/Blocks/Scripts/WorldManager.cs b/Assets/Blocks/Scripts/WorldManager.cs
index bfb7bb4..3f0b40d 100644
--- a/Assets/Blocks/Scripts/WorldManager.cs
+++ b/Assets/Blocks/Scripts/WorldManager.cs
@@ -16,6 +16,10 @@ public class WorldManager : MonoBehaviour
[Tooltip("Можно оставить пустым — создаётся из кода")]
public GameObject chunkPrefab;
+ [Header("Chunk Layer")]
+ [Tooltip("Слой для всех чанков — должен совпадать с blockLayer в BlockPlacer")]
+ public LayerMask chunkLayer;
+
// chunkPos (в чанковых координатах) → Chunk
private readonly Dictionary _chunks = new();
@@ -97,8 +101,11 @@ public class WorldManager : MonoBehaviour
go.transform.position = ChunkData.ChunkToWorld(chunkPos);
+ if (chunkLayer.value != 0)
+ go.layer = Mathf.RoundToInt(Mathf.Log(chunkLayer.value, 2));
+
var chunk = go.GetComponent() ?? go.AddComponent();
- chunk.Initialise(data, registry.ChunkMaterial);
+ chunk.Initialise(data, registry.ChunkMaterial, buildMesh: false);
_chunks[chunkPos] = chunk;
return chunk;
@@ -129,6 +136,16 @@ public class WorldManager : MonoBehaviour
chunk.RebuildMesh();
}
+ ///
+ /// Перестраивает меши всех чанков.
+ /// Вызывать после того как все чанки созданы — исправляет граничные грани.
+ ///
+ public void RebuildAllChunks()
+ {
+ foreach (var chunk in _chunks.Values)
+ chunk.RebuildMesh();
+ }
+
/// Перевод мировой позиции игрока → мировые координаты блока.
public static Vector3Int WorldToBlock(Vector3 worldPosition)
{
diff --git a/Assets/Blocks/Shaders/VoxelLit.shader b/Assets/Blocks/Shaders/VoxelLit.shader
index 55ba99f..9c20fd5 100644
--- a/Assets/Blocks/Shaders/VoxelLit.shader
+++ b/Assets/Blocks/Shaders/VoxelLit.shader
@@ -3,53 +3,108 @@ Shader "Blocks/VoxelLit"
Properties
{
_MainTexArray ("Texture Array", 2DArray) = "" {}
- _Glossiness ("Smoothness", Range(0,1)) = 0.0
- _Metallic ("Metallic", Range(0,1)) = 0.0
}
SubShader
{
Tags { "RenderType"="Opaque" }
- LOD 200
+ LOD 100
+ Cull Off // рендерим обе стороны граней — нужно для видимости стен внутри ям
- CGPROGRAM
- // Standard surface shader с кастомным vertex для передачи texIndex
- #pragma surface surf Standard fullforwardshadows vertex:vert
- #pragma target 3.5
- #pragma require 2darray
-
- UNITY_DECLARE_TEX2DARRAY(_MainTexArray);
-
- struct Input
+ Pass
{
- float2 uv_MainTexArray; // стандартный UV (0-1 по грани)
- float texIndex; // индекс слоя в Texture2DArray
- };
+ Tags { "LightMode"="ForwardBase" }
- half _Glossiness;
- half _Metallic;
+ CGPROGRAM
+ #pragma vertex vert
+ #pragma fragment frag
+ #pragma multi_compile_fog
+ #pragma multi_compile_fwdbase
+ #pragma target 3.5
+ #pragma require 2darray
- // Vertex-функция: читаем texIndex из канала UV1 (mesh.uv2)
- void vert(inout appdata_full v, out Input o)
- {
- UNITY_INITIALIZE_OUTPUT(Input, o);
- o.uv_MainTexArray = v.texcoord.xy;
- o.texIndex = v.texcoord1.x; // UV1.x = индекс текстуры
+ #include "UnityCG.cginc"
+ #include "AutoLight.cginc"
+
+ UNITY_DECLARE_TEX2DARRAY(_MainTexArray);
+
+ struct appdata
+ {
+ float4 vertex : POSITION;
+ float2 uv : TEXCOORD0; // UV грани 0-1
+ float2 uv2 : TEXCOORD1; // x = texIndex, y = face brightness
+ };
+
+ struct v2f
+ {
+ float4 pos : SV_POSITION;
+ float3 uvTex : TEXCOORD0; // xy = UV, z = texIndex
+ float bright : TEXCOORD1; // face brightness (0.5 – 1.0)
+ UNITY_FOG_COORDS(2)
+ SHADOW_COORDS(3)
+ };
+
+ v2f vert(appdata v)
+ {
+ v2f o;
+ o.pos = UnityObjectToClipPos(v.vertex);
+ o.uvTex = float3(v.uv, v.uv2.x);
+ o.bright = v.uv2.y;
+ UNITY_TRANSFER_FOG(o, o.pos);
+ TRANSFER_SHADOW(o);
+ return o;
+ }
+
+ fixed4 frag(v2f i) : SV_Target
+ {
+ fixed4 col = UNITY_SAMPLE_TEX2DARRAY(_MainTexArray, i.uvTex);
+
+ // Minecraft-стиль освещения: фиксированная яркость по направлению грани
+ col.rgb *= i.bright;
+
+ // Тени от directional light
+ fixed shadow = SHADOW_ATTENUATION(i);
+ col.rgb *= lerp(0.5, 1.0, shadow);
+
+ UNITY_APPLY_FOG(i.fogCoord, col);
+ return col;
+ }
+ ENDCG
}
- void surf(Input IN, inout SurfaceOutputStandard o)
+ // Shadow caster pass — нужен чтобы чанки отбрасывали тени
+ Pass
{
- fixed4 c = UNITY_SAMPLE_TEX2DARRAY(
- _MainTexArray,
- float3(IN.uv_MainTexArray, IN.texIndex)
- );
- o.Albedo = c.rgb;
- o.Metallic = _Metallic;
- o.Smoothness = _Glossiness;
- o.Alpha = c.a;
+ Tags { "LightMode"="ShadowCaster" }
+ Cull Off
+
+ CGPROGRAM
+ #pragma vertex vert
+ #pragma fragment frag
+ #pragma multi_compile_shadowcaster
+ #pragma target 3.5
+
+ #include "UnityCG.cginc"
+
+ struct appdata { float4 vertex : POSITION; };
+
+ struct v2f
+ {
+ V2F_SHADOW_CASTER;
+ };
+
+ v2f vert(appdata v)
+ {
+ v2f o;
+ TRANSFER_SHADOW_CASTER_NORMALOFFSET(o)
+ return o;
+ }
+
+ fixed4 frag(v2f i) : SV_Target
+ {
+ SHADOW_CASTER_FRAGMENT(i)
+ }
+ ENDCG
}
- ENDCG
}
-
- FallBack "Diffuse"
}
diff --git a/Assets/Blocks/material.meta b/Assets/Blocks/material.meta
new file mode 100644
index 0000000..5520a10
--- /dev/null
+++ b/Assets/Blocks/material.meta
@@ -0,0 +1,8 @@
+fileFormatVersion: 2
+guid: 75b00cdc4ce553b4087844bae1e992e2
+folderAsset: yes
+DefaultImporter:
+ externalObjects: {}
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/Assets/Blocks/material/tree.mat b/Assets/Blocks/material/tree.mat
new file mode 100644
index 0000000..be25014
--- /dev/null
+++ b/Assets/Blocks/material/tree.mat
@@ -0,0 +1,95 @@
+%YAML 1.1
+%TAG !u! tag:unity3d.com,2011:
+--- !u!21 &2100000
+Material:
+ serializedVersion: 8
+ m_ObjectHideFlags: 0
+ m_CorrespondingSourceObject: {fileID: 0}
+ m_PrefabInstance: {fileID: 0}
+ m_PrefabAsset: {fileID: 0}
+ m_Name: tree
+ m_Shader: {fileID: 46, guid: 0000000000000000f000000000000000, type: 0}
+ m_Parent: {fileID: 0}
+ m_ModifiedSerializedProperties: 0
+ m_ValidKeywords:
+ - _GLOSSYREFLECTIONS_OFF
+ - _SPECULARHIGHLIGHTS_OFF
+ m_InvalidKeywords: []
+ m_LightmapFlags: 4
+ m_EnableInstancingVariants: 1
+ m_DoubleSidedGI: 0
+ m_CustomRenderQueue: -1
+ stringTagMap: {}
+ disabledShaderPasses: []
+ m_LockedProperties: _Metallic _MetallicGlossMap
+ m_SavedProperties:
+ serializedVersion: 3
+ m_TexEnvs:
+ - _BumpMap:
+ m_Texture: {fileID: 0}
+ m_Scale: {x: 1, y: 1}
+ m_Offset: {x: 0, y: 0}
+ - _CrackTex:
+ m_Texture: {fileID: 0}
+ m_Scale: {x: 1, y: 1}
+ m_Offset: {x: 0, y: 0}
+ - _DetailAlbedoMap:
+ m_Texture: {fileID: 0}
+ m_Scale: {x: 1, y: 1}
+ m_Offset: {x: 0, y: 0}
+ - _DetailMask:
+ m_Texture: {fileID: 0}
+ m_Scale: {x: 1, y: 1}
+ m_Offset: {x: 0, y: 0}
+ - _DetailNormalMap:
+ m_Texture: {fileID: 0}
+ m_Scale: {x: 1, y: 1}
+ m_Offset: {x: 0, y: 0}
+ - _EmissionMap:
+ m_Texture: {fileID: 0}
+ m_Scale: {x: 1, y: 1}
+ m_Offset: {x: 0, y: 0}
+ - _MainTex:
+ m_Texture: {fileID: 2800000, guid: 31d7c3b267ede19409f90e3eed1c1266, type: 3}
+ m_Scale: {x: 1, y: 1}
+ m_Offset: {x: 0, y: 0}
+ - _MainTexArray:
+ m_Texture: {fileID: 0}
+ m_Scale: {x: 1, y: 1}
+ m_Offset: {x: 0, y: 0}
+ - _MetallicGlossMap:
+ m_Texture: {fileID: 0}
+ m_Scale: {x: 1, y: 1}
+ m_Offset: {x: 0, y: 0}
+ - _OcclusionMap:
+ m_Texture: {fileID: 0}
+ m_Scale: {x: 1, y: 1}
+ m_Offset: {x: 0, y: 0}
+ - _ParallaxMap:
+ m_Texture: {fileID: 0}
+ m_Scale: {x: 1, y: 1}
+ m_Offset: {x: 0, y: 0}
+ m_Ints: []
+ m_Floats:
+ - _BumpScale: 1
+ - _Cutoff: 0.5
+ - _DetailNormalMapScale: 1
+ - _DstBlend: 0
+ - _GlossMapScale: 1
+ - _Glossiness: 0
+ - _GlossyReflections: 0
+ - _Metallic: 0
+ - _Mode: 0
+ - _OcclusionStrength: 1
+ - _Parallax: 0.02
+ - _Progress: 0
+ - _SmoothnessTextureChannel: 0
+ - _SpecularHighlights: 0
+ - _SrcBlend: 1
+ - _UVSec: 0
+ - _ZWrite: 1
+ m_Colors:
+ - _Color: {r: 1, g: 1, b: 1, a: 1}
+ - _EmissionColor: {r: 0, g: 0, b: 0, a: 1}
+ m_BuildTextureStacks: []
+ m_AllowLocking: 1
diff --git a/Assets/Inventory/Items/ferstitem.asset.meta b/Assets/Blocks/material/tree.mat.meta
similarity index 64%
rename from Assets/Inventory/Items/ferstitem.asset.meta
rename to Assets/Blocks/material/tree.mat.meta
index f87cae9..c476e1c 100644
--- a/Assets/Inventory/Items/ferstitem.asset.meta
+++ b/Assets/Blocks/material/tree.mat.meta
@@ -1,8 +1,8 @@
fileFormatVersion: 2
-guid: d870f627519521f4aa24b9a36766465d
+guid: 2a59d3fb9416740458f1398cf6b2f942
NativeFormatImporter:
externalObjects: {}
- mainObjectFileID: 11400000
+ mainObjectFileID: 2100000
userData:
assetBundleName:
assetBundleVariant:
diff --git a/Assets/Blocks/texturs.meta b/Assets/Blocks/texturs.meta
new file mode 100644
index 0000000..a569cbe
--- /dev/null
+++ b/Assets/Blocks/texturs.meta
@@ -0,0 +1,8 @@
+fileFormatVersion: 2
+guid: ef13a612315aeae43bc2d2c363286de6
+folderAsset: yes
+DefaultImporter:
+ externalObjects: {}
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/Assets/Blocks/texturs/tree.png b/Assets/Blocks/texturs/tree.png
new file mode 100644
index 0000000..619bea4
Binary files /dev/null and b/Assets/Blocks/texturs/tree.png differ
diff --git a/Assets/Blocks/texturs/tree.png.meta b/Assets/Blocks/texturs/tree.png.meta
new file mode 100644
index 0000000..67f8dde
--- /dev/null
+++ b/Assets/Blocks/texturs/tree.png.meta
@@ -0,0 +1,204 @@
+fileFormatVersion: 2
+guid: 31d7c3b267ede19409f90e3eed1c1266
+TextureImporter:
+ internalIDToNameTable: []
+ externalObjects: {}
+ serializedVersion: 13
+ mipmaps:
+ mipMapMode: 0
+ enableMipMap: 0
+ sRGBTexture: 1
+ linearTexture: 0
+ fadeOut: 0
+ borderMipMap: 0
+ mipMapsPreserveCoverage: 0
+ alphaTestReferenceValue: 0.5
+ mipMapFadeDistanceStart: 1
+ mipMapFadeDistanceEnd: 3
+ bumpmap:
+ convertToNormalMap: 0
+ externalNormalMap: 0
+ heightScale: 0.25
+ normalMapFilter: 0
+ flipGreenChannel: 0
+ isReadable: 0
+ streamingMipmaps: 0
+ streamingMipmapsPriority: 0
+ vTOnly: 0
+ ignoreMipmapLimit: 0
+ grayScaleToAlpha: 0
+ generateCubemap: 6
+ cubemapConvolution: 0
+ seamlessCubemap: 0
+ textureFormat: 1
+ maxTextureSize: 2048
+ textureSettings:
+ serializedVersion: 2
+ filterMode: 1
+ aniso: 1
+ mipBias: 0
+ wrapU: 1
+ wrapV: 1
+ wrapW: 1
+ nPOTScale: 0
+ lightmap: 0
+ compressionQuality: 50
+ spriteMode: 2
+ spriteExtrude: 1
+ spriteMeshType: 0
+ alignment: 0
+ spritePivot: {x: 0.5, y: 0.5}
+ spritePixelsToUnits: 100
+ spriteBorder: {x: 0, y: 0, z: 0, w: 0}
+ spriteGenerateFallbackPhysicsShape: 1
+ alphaUsage: 1
+ alphaIsTransparency: 1
+ spriteTessellationDetail: -1
+ textureType: 8
+ textureShape: 1
+ singleChannelComponent: 0
+ flipbookRows: 1
+ flipbookColumns: 1
+ maxTextureSizeSet: 0
+ compressionQualitySet: 0
+ textureFormatSet: 0
+ ignorePngGamma: 0
+ applyGammaDecoding: 0
+ swizzle: 50462976
+ cookieLightType: 0
+ platformSettings:
+ - serializedVersion: 4
+ buildTarget: DefaultTexturePlatform
+ maxTextureSize: 32
+ resizeAlgorithm: 0
+ textureFormat: -1
+ textureCompression: 1
+ compressionQuality: 100
+ crunchedCompression: 0
+ allowsAlphaSplitting: 0
+ overridden: 0
+ ignorePlatformSupport: 0
+ androidETC2FallbackOverride: 0
+ forceMaximumCompressionQuality_BC6H_BC7: 0
+ - serializedVersion: 4
+ buildTarget: Standalone
+ maxTextureSize: 32
+ resizeAlgorithm: 1
+ textureFormat: 12
+ textureCompression: 1
+ compressionQuality: 50
+ crunchedCompression: 0
+ allowsAlphaSplitting: 0
+ overridden: 1
+ ignorePlatformSupport: 0
+ androidETC2FallbackOverride: 0
+ forceMaximumCompressionQuality_BC6H_BC7: 0
+ - serializedVersion: 4
+ buildTarget: WebGL
+ maxTextureSize: 2048
+ resizeAlgorithm: 0
+ textureFormat: -1
+ textureCompression: 1
+ compressionQuality: 50
+ crunchedCompression: 0
+ allowsAlphaSplitting: 0
+ overridden: 0
+ ignorePlatformSupport: 0
+ androidETC2FallbackOverride: 0
+ forceMaximumCompressionQuality_BC6H_BC7: 0
+ spriteSheet:
+ serializedVersion: 2
+ sprites:
+ - serializedVersion: 2
+ name: tree_0
+ rect:
+ serializedVersion: 2
+ x: 0
+ y: 16
+ width: 16
+ height: 16
+ alignment: 0
+ pivot: {x: 0.5, y: 0.5}
+ border: {x: 0, y: 0, z: 0, w: 0}
+ customData:
+ outline: []
+ physicsShape: []
+ tessellationDetail: 0
+ bones: []
+ spriteID: dca6d7bc05d6ee343bc521837ba8af3f
+ internalID: -1348885527
+ vertices: []
+ indices:
+ edges: []
+ weights: []
+ - serializedVersion: 2
+ name: tree_1
+ rect:
+ serializedVersion: 2
+ x: 16
+ y: 16
+ width: 16
+ height: 16
+ alignment: 0
+ pivot: {x: 0, y: 0}
+ border: {x: 0, y: 0, z: 0, w: 0}
+ customData:
+ outline: []
+ physicsShape: []
+ tessellationDetail: 0
+ bones: []
+ spriteID: be4147745dc24b44d8eb775803676697
+ internalID: 394011459
+ vertices: []
+ indices:
+ edges: []
+ weights: []
+ - serializedVersion: 2
+ name: tree_2
+ rect:
+ serializedVersion: 2
+ x: 0
+ y: 0
+ width: 16
+ height: 16
+ alignment: 0
+ pivot: {x: 0, y: 0}
+ border: {x: 0, y: 0, z: 0, w: 0}
+ customData:
+ outline: []
+ physicsShape: []
+ tessellationDetail: 0
+ bones: []
+ spriteID: 84a8f42573bda534a9ca4a34894e22dc
+ internalID: -1937943187
+ vertices: []
+ indices:
+ edges: []
+ weights: []
+ outline: []
+ customData:
+ physicsShape: []
+ bones: []
+ spriteID: b332cdd6f7af3b042972045431002e42
+ internalID: 0
+ vertices: []
+ indices:
+ edges: []
+ weights: []
+ secondaryTextures: []
+ spriteCustomMetadata:
+ entries:
+ - key: SpriteEditor.SliceSettings
+ value: '{"sliceOnImport":false,"gridCellCount":{"x":1.0,"y":1.0},"gridSpriteSize":{"x":64.0,"y":64.0},"gridSpriteOffset":{"x":0.0,"y":0.0},"gridSpritePadding":{"x":0.0,"y":0.0},"pivot":{"x":0.5,"y":0.5},"pivotPixels":{"x":0.0,"y":0.0},"autoSlicingMethod":0,"spriteAlignment":0,"pivotUnitMode":0,"slicingType":0,"keepEmptyRects":false,"isAlternate":false}'
+ - key: SpriteEditor.SliceOnImport
+ value: False
+ nameFileIdTable:
+ tree_0: -1348885527
+ tree_1: 394011459
+ tree_2: -1937943187
+ tree_3: -413478633
+ mipmapLimitGroupName:
+ pSDRemoveMatte: 0
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/Assets/Blocks/texturs/tree1.png b/Assets/Blocks/texturs/tree1.png
new file mode 100644
index 0000000..836fb0a
Binary files /dev/null and b/Assets/Blocks/texturs/tree1.png differ
diff --git a/Assets/Blocks/texturs/tree1.png.meta b/Assets/Blocks/texturs/tree1.png.meta
new file mode 100644
index 0000000..56e7f6b
--- /dev/null
+++ b/Assets/Blocks/texturs/tree1.png.meta
@@ -0,0 +1,130 @@
+fileFormatVersion: 2
+guid: 3009578ee03d9ed46a97978c08168eee
+TextureImporter:
+ internalIDToNameTable: []
+ externalObjects: {}
+ serializedVersion: 13
+ mipmaps:
+ mipMapMode: 0
+ enableMipMap: 1
+ sRGBTexture: 1
+ linearTexture: 0
+ fadeOut: 0
+ borderMipMap: 0
+ mipMapsPreserveCoverage: 0
+ alphaTestReferenceValue: 0.5
+ mipMapFadeDistanceStart: 1
+ mipMapFadeDistanceEnd: 3
+ bumpmap:
+ convertToNormalMap: 0
+ externalNormalMap: 0
+ heightScale: 0.25
+ normalMapFilter: 0
+ flipGreenChannel: 0
+ isReadable: 0
+ streamingMipmaps: 0
+ streamingMipmapsPriority: 0
+ vTOnly: 0
+ ignoreMipmapLimit: 0
+ grayScaleToAlpha: 0
+ generateCubemap: 6
+ cubemapConvolution: 0
+ seamlessCubemap: 0
+ textureFormat: 1
+ maxTextureSize: 2048
+ textureSettings:
+ serializedVersion: 2
+ filterMode: 1
+ aniso: 1
+ mipBias: 0
+ wrapU: 0
+ wrapV: 0
+ wrapW: 0
+ nPOTScale: 1
+ lightmap: 0
+ compressionQuality: 50
+ spriteMode: 0
+ spriteExtrude: 1
+ spriteMeshType: 1
+ alignment: 0
+ spritePivot: {x: 0.5, y: 0.5}
+ spritePixelsToUnits: 100
+ spriteBorder: {x: 0, y: 0, z: 0, w: 0}
+ spriteGenerateFallbackPhysicsShape: 1
+ alphaUsage: 1
+ alphaIsTransparency: 0
+ spriteTessellationDetail: -1
+ textureType: 0
+ textureShape: 1
+ singleChannelComponent: 0
+ flipbookRows: 1
+ flipbookColumns: 1
+ maxTextureSizeSet: 0
+ compressionQualitySet: 0
+ textureFormatSet: 0
+ ignorePngGamma: 0
+ applyGammaDecoding: 0
+ swizzle: 50462976
+ cookieLightType: 0
+ platformSettings:
+ - serializedVersion: 4
+ buildTarget: DefaultTexturePlatform
+ maxTextureSize: 32
+ resizeAlgorithm: 1
+ textureFormat: -1
+ textureCompression: 3
+ compressionQuality: 50
+ crunchedCompression: 0
+ allowsAlphaSplitting: 0
+ overridden: 0
+ ignorePlatformSupport: 0
+ androidETC2FallbackOverride: 0
+ forceMaximumCompressionQuality_BC6H_BC7: 0
+ - serializedVersion: 4
+ buildTarget: Standalone
+ maxTextureSize: 32
+ resizeAlgorithm: 1
+ textureFormat: 10
+ textureCompression: 1
+ compressionQuality: 50
+ crunchedCompression: 0
+ allowsAlphaSplitting: 0
+ overridden: 1
+ ignorePlatformSupport: 0
+ androidETC2FallbackOverride: 0
+ forceMaximumCompressionQuality_BC6H_BC7: 0
+ - serializedVersion: 4
+ buildTarget: WebGL
+ maxTextureSize: 2048
+ resizeAlgorithm: 0
+ textureFormat: -1
+ textureCompression: 1
+ compressionQuality: 50
+ crunchedCompression: 0
+ allowsAlphaSplitting: 0
+ overridden: 0
+ ignorePlatformSupport: 0
+ androidETC2FallbackOverride: 0
+ forceMaximumCompressionQuality_BC6H_BC7: 0
+ spriteSheet:
+ serializedVersion: 2
+ sprites: []
+ outline: []
+ customData:
+ physicsShape: []
+ bones: []
+ spriteID:
+ internalID: 0
+ vertices: []
+ indices:
+ edges: []
+ weights: []
+ secondaryTextures: []
+ spriteCustomMetadata:
+ entries: []
+ nameFileIdTable: {}
+ mipmapLimitGroupName:
+ pSDRemoveMatte: 0
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/Assets/Blocks/texturs/tree2.png b/Assets/Blocks/texturs/tree2.png
new file mode 100644
index 0000000..b5ec82b
Binary files /dev/null and b/Assets/Blocks/texturs/tree2.png differ
diff --git a/Assets/Blocks/texturs/tree2.png.meta b/Assets/Blocks/texturs/tree2.png.meta
new file mode 100644
index 0000000..b23d947
--- /dev/null
+++ b/Assets/Blocks/texturs/tree2.png.meta
@@ -0,0 +1,130 @@
+fileFormatVersion: 2
+guid: 640e614afcdf0cc42ae02e2b478ae512
+TextureImporter:
+ internalIDToNameTable: []
+ externalObjects: {}
+ serializedVersion: 13
+ mipmaps:
+ mipMapMode: 0
+ enableMipMap: 1
+ sRGBTexture: 1
+ linearTexture: 0
+ fadeOut: 0
+ borderMipMap: 0
+ mipMapsPreserveCoverage: 0
+ alphaTestReferenceValue: 0.5
+ mipMapFadeDistanceStart: 1
+ mipMapFadeDistanceEnd: 3
+ bumpmap:
+ convertToNormalMap: 0
+ externalNormalMap: 0
+ heightScale: 0.25
+ normalMapFilter: 0
+ flipGreenChannel: 0
+ isReadable: 0
+ streamingMipmaps: 0
+ streamingMipmapsPriority: 0
+ vTOnly: 0
+ ignoreMipmapLimit: 0
+ grayScaleToAlpha: 0
+ generateCubemap: 6
+ cubemapConvolution: 0
+ seamlessCubemap: 0
+ textureFormat: 1
+ maxTextureSize: 2048
+ textureSettings:
+ serializedVersion: 2
+ filterMode: 1
+ aniso: 1
+ mipBias: 0
+ wrapU: 0
+ wrapV: 0
+ wrapW: 0
+ nPOTScale: 1
+ lightmap: 0
+ compressionQuality: 50
+ spriteMode: 0
+ spriteExtrude: 1
+ spriteMeshType: 1
+ alignment: 0
+ spritePivot: {x: 0.5, y: 0.5}
+ spritePixelsToUnits: 100
+ spriteBorder: {x: 0, y: 0, z: 0, w: 0}
+ spriteGenerateFallbackPhysicsShape: 1
+ alphaUsage: 1
+ alphaIsTransparency: 0
+ spriteTessellationDetail: -1
+ textureType: 0
+ textureShape: 1
+ singleChannelComponent: 0
+ flipbookRows: 1
+ flipbookColumns: 1
+ maxTextureSizeSet: 0
+ compressionQualitySet: 0
+ textureFormatSet: 0
+ ignorePngGamma: 0
+ applyGammaDecoding: 0
+ swizzle: 50462976
+ cookieLightType: 0
+ platformSettings:
+ - serializedVersion: 4
+ buildTarget: DefaultTexturePlatform
+ maxTextureSize: 32
+ resizeAlgorithm: 1
+ textureFormat: -1
+ textureCompression: 3
+ compressionQuality: 50
+ crunchedCompression: 0
+ allowsAlphaSplitting: 0
+ overridden: 0
+ ignorePlatformSupport: 0
+ androidETC2FallbackOverride: 0
+ forceMaximumCompressionQuality_BC6H_BC7: 0
+ - serializedVersion: 4
+ buildTarget: Standalone
+ maxTextureSize: 32
+ resizeAlgorithm: 1
+ textureFormat: 10
+ textureCompression: 1
+ compressionQuality: 50
+ crunchedCompression: 0
+ allowsAlphaSplitting: 0
+ overridden: 1
+ ignorePlatformSupport: 0
+ androidETC2FallbackOverride: 0
+ forceMaximumCompressionQuality_BC6H_BC7: 0
+ - serializedVersion: 4
+ buildTarget: WebGL
+ maxTextureSize: 2048
+ resizeAlgorithm: 0
+ textureFormat: -1
+ textureCompression: 1
+ compressionQuality: 50
+ crunchedCompression: 0
+ allowsAlphaSplitting: 0
+ overridden: 0
+ ignorePlatformSupport: 0
+ androidETC2FallbackOverride: 0
+ forceMaximumCompressionQuality_BC6H_BC7: 0
+ spriteSheet:
+ serializedVersion: 2
+ sprites: []
+ outline: []
+ customData:
+ physicsShape: []
+ bones: []
+ spriteID:
+ internalID: 0
+ vertices: []
+ indices:
+ edges: []
+ weights: []
+ secondaryTextures: []
+ spriteCustomMetadata:
+ entries: []
+ nameFileIdTable: {}
+ mipmapLimitGroupName:
+ pSDRemoveMatte: 0
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/Assets/Blocks/texturs/tree_icon.PNG b/Assets/Blocks/texturs/tree_icon.PNG
new file mode 100644
index 0000000..93af55b
Binary files /dev/null and b/Assets/Blocks/texturs/tree_icon.PNG differ
diff --git a/Assets/Blocks/texturs/tree_icon.PNG.meta b/Assets/Blocks/texturs/tree_icon.PNG.meta
new file mode 100644
index 0000000..25a8b61
--- /dev/null
+++ b/Assets/Blocks/texturs/tree_icon.PNG.meta
@@ -0,0 +1,130 @@
+fileFormatVersion: 2
+guid: 63b56781d36f85e49923a6b7b50381e7
+TextureImporter:
+ internalIDToNameTable: []
+ externalObjects: {}
+ serializedVersion: 13
+ mipmaps:
+ mipMapMode: 0
+ enableMipMap: 0
+ sRGBTexture: 1
+ linearTexture: 0
+ fadeOut: 0
+ borderMipMap: 0
+ mipMapsPreserveCoverage: 0
+ alphaTestReferenceValue: 0.5
+ mipMapFadeDistanceStart: 1
+ mipMapFadeDistanceEnd: 3
+ bumpmap:
+ convertToNormalMap: 0
+ externalNormalMap: 0
+ heightScale: 0.25
+ normalMapFilter: 0
+ flipGreenChannel: 0
+ isReadable: 0
+ streamingMipmaps: 0
+ streamingMipmapsPriority: 0
+ vTOnly: 0
+ ignoreMipmapLimit: 0
+ grayScaleToAlpha: 0
+ generateCubemap: 6
+ cubemapConvolution: 0
+ seamlessCubemap: 0
+ textureFormat: 1
+ maxTextureSize: 2048
+ textureSettings:
+ serializedVersion: 2
+ filterMode: 0
+ aniso: 1
+ mipBias: 0
+ wrapU: 1
+ wrapV: 1
+ wrapW: 1
+ nPOTScale: 0
+ lightmap: 0
+ compressionQuality: 50
+ spriteMode: 1
+ spriteExtrude: 1
+ spriteMeshType: 0
+ alignment: 0
+ spritePivot: {x: 0.5, y: 0.5}
+ spritePixelsToUnits: 100
+ spriteBorder: {x: 0, y: 0, z: 0, w: 0}
+ spriteGenerateFallbackPhysicsShape: 0
+ alphaUsage: 1
+ alphaIsTransparency: 1
+ spriteTessellationDetail: -1
+ textureType: 8
+ textureShape: 1
+ singleChannelComponent: 0
+ flipbookRows: 1
+ flipbookColumns: 1
+ maxTextureSizeSet: 0
+ compressionQualitySet: 0
+ textureFormatSet: 0
+ ignorePngGamma: 0
+ applyGammaDecoding: 0
+ swizzle: 50462976
+ cookieLightType: 0
+ platformSettings:
+ - serializedVersion: 4
+ buildTarget: DefaultTexturePlatform
+ maxTextureSize: 128
+ resizeAlgorithm: 1
+ textureFormat: -1
+ textureCompression: 1
+ compressionQuality: 50
+ crunchedCompression: 0
+ allowsAlphaSplitting: 0
+ overridden: 0
+ ignorePlatformSupport: 0
+ androidETC2FallbackOverride: 0
+ forceMaximumCompressionQuality_BC6H_BC7: 0
+ - serializedVersion: 4
+ buildTarget: Standalone
+ maxTextureSize: 128
+ resizeAlgorithm: 1
+ textureFormat: 12
+ textureCompression: 1
+ compressionQuality: 50
+ crunchedCompression: 0
+ allowsAlphaSplitting: 0
+ overridden: 1
+ ignorePlatformSupport: 0
+ androidETC2FallbackOverride: 0
+ forceMaximumCompressionQuality_BC6H_BC7: 0
+ - serializedVersion: 4
+ buildTarget: WebGL
+ maxTextureSize: 2048
+ resizeAlgorithm: 0
+ textureFormat: -1
+ textureCompression: 1
+ compressionQuality: 50
+ crunchedCompression: 0
+ allowsAlphaSplitting: 0
+ overridden: 0
+ ignorePlatformSupport: 0
+ androidETC2FallbackOverride: 0
+ forceMaximumCompressionQuality_BC6H_BC7: 0
+ spriteSheet:
+ serializedVersion: 2
+ sprites: []
+ outline: []
+ customData:
+ physicsShape: []
+ bones: []
+ spriteID: 5e97eb03825dee720800000000000000
+ internalID: 0
+ vertices: []
+ indices:
+ edges: []
+ weights: []
+ secondaryTextures: []
+ spriteCustomMetadata:
+ entries: []
+ nameFileIdTable: {}
+ mipmapLimitGroupName:
+ pSDRemoveMatte: 0
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/Assets/Blocks/tree.prefab b/Assets/Blocks/tree.prefab
new file mode 100644
index 0000000..256d2b8
--- /dev/null
+++ b/Assets/Blocks/tree.prefab
@@ -0,0 +1,124 @@
+%YAML 1.1
+%TAG !u! tag:unity3d.com,2011:
+--- !u!1001 &1834211952878912991
+PrefabInstance:
+ m_ObjectHideFlags: 0
+ serializedVersion: 2
+ m_Modification:
+ serializedVersion: 3
+ m_TransformParent: {fileID: 0}
+ m_Modifications:
+ - target: {fileID: -8679921383154817045, guid: 9491bc8c1f13b6541bb223ae6d55788a, type: 3}
+ propertyPath: m_LocalPosition.x
+ value: 0.66041523
+ objectReference: {fileID: 0}
+ - target: {fileID: -8679921383154817045, guid: 9491bc8c1f13b6541bb223ae6d55788a, type: 3}
+ propertyPath: m_LocalPosition.y
+ value: 1
+ objectReference: {fileID: 0}
+ - target: {fileID: -8679921383154817045, guid: 9491bc8c1f13b6541bb223ae6d55788a, type: 3}
+ propertyPath: m_LocalPosition.z
+ value: 3.3843179
+ objectReference: {fileID: 0}
+ - target: {fileID: -8679921383154817045, guid: 9491bc8c1f13b6541bb223ae6d55788a, type: 3}
+ propertyPath: m_LocalRotation.w
+ value: 1
+ objectReference: {fileID: 0}
+ - target: {fileID: -8679921383154817045, guid: 9491bc8c1f13b6541bb223ae6d55788a, type: 3}
+ propertyPath: m_LocalRotation.x
+ value: 0
+ objectReference: {fileID: 0}
+ - target: {fileID: -8679921383154817045, guid: 9491bc8c1f13b6541bb223ae6d55788a, type: 3}
+ propertyPath: m_LocalRotation.y
+ value: -0
+ objectReference: {fileID: 0}
+ - target: {fileID: -8679921383154817045, guid: 9491bc8c1f13b6541bb223ae6d55788a, type: 3}
+ propertyPath: m_LocalRotation.z
+ value: -0
+ objectReference: {fileID: 0}
+ - target: {fileID: -8679921383154817045, guid: 9491bc8c1f13b6541bb223ae6d55788a, type: 3}
+ propertyPath: m_LocalEulerAnglesHint.x
+ value: 0
+ objectReference: {fileID: 0}
+ - target: {fileID: -8679921383154817045, guid: 9491bc8c1f13b6541bb223ae6d55788a, type: 3}
+ propertyPath: m_LocalEulerAnglesHint.y
+ value: 0
+ objectReference: {fileID: 0}
+ - target: {fileID: -8679921383154817045, guid: 9491bc8c1f13b6541bb223ae6d55788a, type: 3}
+ propertyPath: m_LocalEulerAnglesHint.z
+ value: 0
+ objectReference: {fileID: 0}
+ - target: {fileID: -7635826562936255635, guid: 9491bc8c1f13b6541bb223ae6d55788a, type: 3}
+ propertyPath: m_CastShadows
+ value: 0
+ objectReference: {fileID: 0}
+ - target: {fileID: -7635826562936255635, guid: 9491bc8c1f13b6541bb223ae6d55788a, type: 3}
+ propertyPath: m_MotionVectors
+ value: 1
+ objectReference: {fileID: 0}
+ - target: {fileID: -7635826562936255635, guid: 9491bc8c1f13b6541bb223ae6d55788a, type: 3}
+ propertyPath: m_RayTracingMode
+ value: 1
+ objectReference: {fileID: 0}
+ - target: {fileID: -7635826562936255635, guid: 9491bc8c1f13b6541bb223ae6d55788a, type: 3}
+ propertyPath: m_Materials.Array.size
+ value: 1
+ objectReference: {fileID: 0}
+ - target: {fileID: -7635826562936255635, guid: 9491bc8c1f13b6541bb223ae6d55788a, type: 3}
+ propertyPath: 'm_Materials.Array.data[0]'
+ value:
+ objectReference: {fileID: 2100000, guid: 2a59d3fb9416740458f1398cf6b2f942, type: 2}
+ - target: {fileID: -7635826562936255635, guid: 9491bc8c1f13b6541bb223ae6d55788a, type: 3}
+ propertyPath: 'm_Materials.Array.data[1]'
+ value:
+ objectReference: {fileID: 2100000, guid: 2a59d3fb9416740458f1398cf6b2f942, type: 2}
+ - target: {fileID: 919132149155446097, guid: 9491bc8c1f13b6541bb223ae6d55788a, type: 3}
+ propertyPath: m_Name
+ value: tree
+ objectReference: {fileID: 0}
+ - target: {fileID: 919132149155446097, guid: 9491bc8c1f13b6541bb223ae6d55788a, type: 3}
+ propertyPath: m_Layer
+ value: 7
+ objectReference: {fileID: 0}
+ - target: {fileID: 8164078558771037576, guid: 9491bc8c1f13b6541bb223ae6d55788a, type: 3}
+ propertyPath: m_Layer
+ value: 0
+ objectReference: {fileID: 0}
+ - target: {fileID: 8164078558771037576, guid: 9491bc8c1f13b6541bb223ae6d55788a, type: 3}
+ propertyPath: m_StaticEditorFlags
+ value: 0
+ objectReference: {fileID: 0}
+ m_RemovedComponents: []
+ m_RemovedGameObjects: []
+ m_AddedGameObjects: []
+ m_AddedComponents:
+ - targetCorrespondingSourceObject: {fileID: 919132149155446097, guid: 9491bc8c1f13b6541bb223ae6d55788a, type: 3}
+ insertIndex: -1
+ addedObject: {fileID: 6307796976124268661}
+ m_SourcePrefab: {fileID: 100100000, guid: 9491bc8c1f13b6541bb223ae6d55788a, type: 3}
+--- !u!1 &1564165088969144462 stripped
+GameObject:
+ m_CorrespondingSourceObject: {fileID: 919132149155446097, guid: 9491bc8c1f13b6541bb223ae6d55788a, type: 3}
+ m_PrefabInstance: {fileID: 1834211952878912991}
+ m_PrefabAsset: {fileID: 0}
+--- !u!65 &6307796976124268661
+BoxCollider:
+ m_ObjectHideFlags: 0
+ m_CorrespondingSourceObject: {fileID: 0}
+ m_PrefabInstance: {fileID: 0}
+ m_PrefabAsset: {fileID: 0}
+ m_GameObject: {fileID: 1564165088969144462}
+ m_Material: {fileID: 0}
+ m_IncludeLayers:
+ serializedVersion: 2
+ m_Bits: 0
+ m_ExcludeLayers:
+ serializedVersion: 2
+ m_Bits: 0
+ m_LayerOverridePriority: 0
+ m_IsTrigger: 0
+ m_ProvidesContacts: 0
+ m_Enabled: 1
+ serializedVersion: 3
+ m_Size: {x: 2, y: 2, z: 2}
+ m_Center: {x: 0, y: 0, z: 0}
diff --git a/Assets/Items/ferstitem123.prefab.meta b/Assets/Blocks/tree.prefab.meta
similarity index 74%
rename from Assets/Items/ferstitem123.prefab.meta
rename to Assets/Blocks/tree.prefab.meta
index dc204c0..8016439 100644
--- a/Assets/Items/ferstitem123.prefab.meta
+++ b/Assets/Blocks/tree.prefab.meta
@@ -1,5 +1,5 @@
fileFormatVersion: 2
-guid: 0e4347f1177decb4a8671c25fe736183
+guid: 3ae36dcb84d70194993d12a9f047bb1c
PrefabImporter:
externalObjects: {}
userData:
diff --git a/Assets/Inventory/Items/ferstitem.asset b/Assets/Inventory/Items/ferstitem.asset
deleted file mode 100644
index 9bf0a57..0000000
--- a/Assets/Inventory/Items/ferstitem.asset
+++ /dev/null
@@ -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: ferstitem
- m_EditorClassIdentifier: Assembly-CSharp::ItemData
- id: c3b1d462-dc84-4d7a-8463-34ffbde783d9
- itemName: ferstitem
- description: ferstitem
- type: 5
- 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
diff --git a/Assets/Inventory/Items/ferstitem123.asset b/Assets/Inventory/Items/ferstitem123.asset
deleted file mode 100644
index 831f441..0000000
--- a/Assets/Inventory/Items/ferstitem123.asset
+++ /dev/null
@@ -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: ferstitem123
- m_EditorClassIdentifier: Assembly-CSharp::ItemData
- id: 4b147ba6-462a-4f90-9d00-29089fed390a
- itemName: ferstitem123
- description: 123
- type: 5
- modelPrefab: {fileID: 8569222662204961130, guid: 06e51a4df39df524397e91edba2a833d, 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
diff --git a/Assets/Inventory/Items/NewItem.asset b/Assets/Inventory/Items/tree.asset
similarity index 67%
rename from Assets/Inventory/Items/NewItem.asset
rename to Assets/Inventory/Items/tree.asset
index 67f6105..a2676b6 100644
--- a/Assets/Inventory/Items/NewItem.asset
+++ b/Assets/Inventory/Items/tree.asset
@@ -10,14 +10,14 @@ MonoBehaviour:
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: 5741b63764436354ebad192c9b71f06c, type: 3}
- m_Name: newItem
+ m_Name: tree
m_EditorClassIdentifier: Assembly-CSharp::ItemData
- id: c58a6ea4-f064-4392-becd-3b4c2b17cd06
- itemName: newItem
- description: 123123
- type: 5
- modelPrefab: {fileID: 282714382156279063, guid: 4fcbba5b8725e254f98c052c4db89e02, type: 3}
- icon: {fileID: 0}
+ id: f1f81603-393a-4a74-8c41-a9efe9f14e9e
+ itemName: tree
+ description: tree
+ type: 0
+ modelPrefab: {fileID: 2501859741750806132, guid: fe90e1e2b9dde0943b665ca3768153ae, type: 3}
+ icon: {fileID: 21300000, guid: 63b56781d36f85e49923a6b7b50381e7, type: 3}
maxStack: 64
isCraftable: 0
craftingRecipe:
diff --git a/Assets/Inventory/Items/NewItem.asset.meta b/Assets/Inventory/Items/tree.asset.meta
similarity index 79%
rename from Assets/Inventory/Items/NewItem.asset.meta
rename to Assets/Inventory/Items/tree.asset.meta
index 83ebba2..249adb3 100644
--- a/Assets/Inventory/Items/NewItem.asset.meta
+++ b/Assets/Inventory/Items/tree.asset.meta
@@ -1,5 +1,5 @@
fileFormatVersion: 2
-guid: 20cff4d8f616b1140b2264c6f049ba8a
+guid: 131ca9b5c83edfe4d9c35a6ef4a380a5
NativeFormatImporter:
externalObjects: {}
mainObjectFileID: 11400000
diff --git a/Assets/Inventory/Scripts/CraftingManager.cs b/Assets/Inventory/Scripts/CraftingManager.cs
index 25cd50a..2119de4 100644
--- a/Assets/Inventory/Scripts/CraftingManager.cs
+++ b/Assets/Inventory/Scripts/CraftingManager.cs
@@ -21,9 +21,15 @@ public class CraftingManager : MonoBehaviour
void Awake()
{
if (Instance == null)
+ {
Instance = this;
+ DontDestroyOnLoad(gameObject);
+ }
else
+ {
Destroy(gameObject);
+ return;
+ }
_recipeDict = new Dictionary();
foreach (var recipe in recipes)
diff --git a/Assets/Inventory/Scripts/InventoryDragDrop.cs b/Assets/Inventory/Scripts/InventoryDragDrop.cs
index 675a2eb..ad6ea9d 100644
--- a/Assets/Inventory/Scripts/InventoryDragDrop.cs
+++ b/Assets/Inventory/Scripts/InventoryDragDrop.cs
@@ -3,86 +3,84 @@ using UnityEngine.EventSystems;
using UnityEngine.UI;
///
-/// Обработка Drag & Drop предметов между слотами и выброс за пределы инвентаря
+/// Drag & Drop предметов между слотами.
+/// Один общий DragIconCanvas на все слоты — создаётся при первом старте.
///
public class InventoryDragDrop : MonoBehaviour, IBeginDragHandler, IDragHandler, IEndDragHandler, IPointerEnterHandler, IPointerExitHandler
{
public Slot slot;
public int slotIndex;
- [Header("Drag Visual")]
- [SerializeField] private RectTransform dragIcon;
- [SerializeField] private Image dragImage;
- [SerializeField] private float dragIconScale = 1.2f;
+ [SerializeField] private float dragIconScale = 1.2f;
+ [SerializeField] private bool allowDropOutside = true;
+ [SerializeField] private float dropThreshold = 100f;
- [Header("Drop Settings")]
- [SerializeField] private bool allowDropOutside = true;
- [SerializeField] private float dropThreshold = 100f; // пикселей за пределами инвентаря
+ // ── Общий на все слоты drag-icon ─────────────────────────────────────────
+ private static GameObject _sharedCanvas;
+ private static RectTransform _sharedIcon;
+ private static Image _sharedImage;
- private Canvas _canvas;
- private CanvasGroup _canvasGroup;
- private bool _isDragging;
- private Vector2 _dragStartPosition;
+ // ── Per-instance поля ─────────────────────────────────────────────────────
+ private CanvasGroup _canvasGroup;
+ private bool _isDragging;
private RectTransform _inventoryPanelRect;
+ // ── Unity lifecycle ───────────────────────────────────────────────────────
+
void Start()
{
- _canvas = GetComponentInParent