Perekyp/Assets/Scripts/Car/Part/CarPartMountZone.cs

166 lines
5.7 KiB
C#
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

using UnityEngine;
public class CarPartMountZone : MonoBehaviour, IInteractable
{
private CarPart targetPart;
private Collider zoneCollider;
private MeshRenderer ghostRenderer;
private PlayerHands cachedHands;
private float mountDuration = 1.2f;
private float currentMountProgress = 0f;
private bool hasSeparateBolts = false;
public void Initialize(CarPart part)
{
targetPart = part;
gameObject.layer = part.gameObject.layer;
cachedHands = FindAnyObjectByType<PlayerHands>();
hasSeparateBolts = part.GetComponentsInChildren<WheelBolt>(true).Length > 0;
if (part.Data != null && part.Data.boltDuration > 0f)
mountDuration = part.Data.boltDuration;
MeshFilter sourceFilter = part.GetComponentInChildren<MeshFilter>();
// Для колеса создаем удобную широкую сферу вокруг ступицы, чтобы луч всегда попадал с первого раза
if (hasSeparateBolts)
{
SphereCollider sphere = gameObject.AddComponent<SphereCollider>();
if (sourceFilter != null && sourceFilter.sharedMesh != null)
sphere.center = sourceFilter.sharedMesh.bounds.center;
sphere.radius = 0.48f;
sphere.isTrigger = true;
zoneCollider = sphere;
}
else
{
Collider sourceCollider = part.GetComponent<Collider>();
if (sourceCollider is BoxCollider sourceBox)
{
BoxCollider box = gameObject.AddComponent<BoxCollider>();
box.center = sourceBox.center;
box.size = sourceBox.size;
box.isTrigger = true;
zoneCollider = box;
}
else if (sourceCollider is MeshCollider sourceMesh)
{
MeshCollider meshCol = gameObject.AddComponent<MeshCollider>();
meshCol.sharedMesh = sourceMesh.sharedMesh;
meshCol.convex = true;
meshCol.isTrigger = true;
zoneCollider = meshCol;
}
else
{
SphereCollider sphere = gameObject.AddComponent<SphereCollider>();
sphere.radius = 0.6f;
sphere.isTrigger = true;
zoneCollider = sphere;
}
}
if (sourceFilter != null && sourceFilter.sharedMesh != null)
{
MeshFilter mf = gameObject.AddComponent<MeshFilter>();
mf.sharedMesh = sourceFilter.sharedMesh;
ghostRenderer = gameObject.AddComponent<MeshRenderer>();
ghostRenderer.shadowCastingMode = UnityEngine.Rendering.ShadowCastingMode.Off;
Material sharedGhostMat = part.Data != null ? part.Data.ghostMaterial : null;
if (sharedGhostMat != null)
{
ghostRenderer.sharedMaterial = sharedGhostMat;
}
else
{
Material fallbackMat = new Material(Shader.Find("Universal Render Pipeline/Unlit"));
fallbackMat.color = new Color(0.2f, 0.9f, 0.3f, 0.4f);
ghostRenderer.material = fallbackMat;
}
}
UpdateZoneVisibility();
}
private void Update()
{
UpdateZoneVisibility();
}
private void UpdateZoneVisibility()
{
if (cachedHands == null)
cachedHands = FindAnyObjectByType<PlayerHands>();
bool isHoldingTarget = cachedHands != null && cachedHands.IsHolding && cachedHands.CurrentPart == targetPart;
if (zoneCollider != null && zoneCollider.enabled != isHoldingTarget)
zoneCollider.enabled = isHoldingTarget;
if (ghostRenderer != null && ghostRenderer.enabled != isHoldingTarget)
ghostRenderer.enabled = isHoldingTarget;
if (!isHoldingTarget)
currentMountProgress = 0f;
}
public string GetPrompt()
{
if (targetPart == null) return string.Empty;
if (cachedHands == null || !cachedHands.IsHolding || cachedHands.CurrentPart != targetPart)
return string.Empty;
string partTitle = targetPart.Data != null ? targetPart.Data.partName : "Деталь";
// Колесо надевается на ступицу сразу при нажатии E или ЛКМ
if (hasSeparateBolts)
{
if (Input.GetKeyDown(KeyCode.E) || Input.GetMouseButtonDown(0))
{
CompleteInstall();
return string.Empty;
}
return $"[E / ЛКМ] Надеть {partTitle} на ступицу";
}
if (Input.GetKey(KeyCode.E))
{
currentMountProgress += Time.deltaTime;
if (currentMountProgress >= mountDuration)
{
CompleteInstall();
return string.Empty;
}
int percent = Mathf.RoundToInt(Mathf.Clamp01(currentMountProgress / mountDuration) * 100f);
return $"Закручиваем болты: {partTitle}... {percent}%";
}
else
{
currentMountProgress = 0f;
}
return $"[Удерживать E] Установить {partTitle}";
}
public void Interact(GameObject interactor)
{
if (hasSeparateBolts && cachedHands != null && cachedHands.IsHolding && cachedHands.CurrentPart == targetPart)
{
CompleteInstall();
}
}
private void CompleteInstall()
{
if (cachedHands == null || targetPart == null) return;
cachedHands.ClearHandAfterInstall();
targetPart.Install();
Destroy(gameObject);
}
}