привет короче есть такая система using System.Collections.Generic;
using UnityEngine;

public class ArrowManager : StaticInstance<ArrowManager>
{
    [Header("Arrow Settings")]
    public GameObject arrowPrefab; // Префаб стрелочки
    private List<GameObject> activeArrows = new List<GameObject>();


    /// <summary>
    /// Очищает все текущие стрелочки.
    /// </summary>
    public void ClearArrows()
    {
        foreach (var arrow in activeArrows)
        {
            Destroy(arrow);
        }
        activeArrows.Clear();
    }

    /// <summary>
    /// Создаёт стрелочки для переданных целей.
    /// </summary>
    /// <param name="targets">Список GameObject, на которые нужно указать стрелками.</param>
    public void CreateArrows(List<GameObject> targets)
    {
        ClearArrows();

        foreach (var target in targets)
        {
            if (target == null)
                continue;

            GameObject arrow = Instantiate(arrowPrefab, target.transform.position, Quaternion.identity);
            activeArrows.Add(arrow);
        }
    }
} мне надо чтобы эта система была задействована в моих блюпринт штуках смотри типо показывается этап блюпринтов и надо найти все объекты драгабл обжект с такими же именами как в блюпринтах (имена могут повторятся) и на всех них заспавнить стрелку ну с помощью метода из стрелок манагенр. и также когда схвачу объект должны появится только стрелки на нужных блюпринтах куда этот объект можно поставить понял? вот коды using System.Collections.Generic;
using AYellowpaper.SerializedCollections;
using EasyButtons;
using UnityEngine;
using UnityEngine.Events;

public class BlueprintManager : StaticInstance<BlueprintManager>
{
    public List<Blueprint> blueprints;
    public UnityEvent onAllBlueprintsFilled;

    public int currentStageIndex = 0;

    public SerializedDictionary<int, List<Blueprint>> blueprintsByStage =
        new SerializedDictionary<int, List<Blueprint>>();

    private int totalStages = 0;

    public void ClearAll()
    {
        blueprints.Clear();
        blueprintsByStage.Clear();
        currentStageIndex = 0;
        BlueprintUIManager.Instance.SetUIActive(false);
    }

    public void SubscribeAllBlueprints(List<DronePart> droneParts, bool showUI)
    {
        ClearAll();

        // Подписываемся на события заполнения каждого блюпринта
        foreach (var dronePart in droneParts)
        {
            if (dronePart.TryGetComponent(out Blueprint blueprint))
            {
                if (blueprint.stageIndex == -1)
                {
                    Debug.LogError("Not signet blueprint", blueprint);
                }
                
                if (!blueprintsByStage.ContainsKey(blueprint.stageIndex))
                {
                    blueprintsByStage[blueprint.stageIndex] = new List<Blueprint>();
                }

                blueprintsByStage[blueprint.stageIndex].Add(blueprint);

                // Подписываемся на событие заполнения блюпринта
                blueprint.OnBlueprintFilled += OnBlueprintFilled;

                // Устанавливаем видимость блюпринта в зависимости от текущего этапа
                if (blueprint.stageIndex == currentStageIndex)
                {
                    blueprint.gameObject.SetActive(true);
                }
                else
                {
                    blueprint.gameObject.SetActive(false);
                }

                blueprints.Add(blueprint);
            }
        }

        // Определяем общее количество этапов
        totalStages = blueprintsByStage.Keys.Count;

        BlueprintUIManager.Instance.SetUIActive(showUI);
        UpdateUI();
    }

    private void OnBlueprintFilled(Blueprint bp)
    {
        NotifyExamManager();
        // Проверяем, заполнены ли все блюпринты текущего этапа
        bool stageCompleted = true;
        foreach (Blueprint blueprint in blueprintsByStage[currentStageIndex])
        {
            if (!blueprint.IsFilled)
            {
                stageCompleted = false;
                break;
            }
        }

        
        UpdateUI();

        if (stageCompleted)
        {
            ProceedToNextStage();
        }
    }

    [Button]
    private void ProceedToNextStage()
    {
        // Скрываем блюпринты предыдущего этапа
        foreach (Blueprint bp in blueprintsByStage[currentStageIndex])
        {
            bp.gameObject.SetActive(false);
        }

        currentStageIndex++;

        // Проверяем, есть ли следующий этап
        if (blueprintsByStage.ContainsKey(currentStageIndex))
        {
            // Показываем блюпринты нового этапа
            foreach (Blueprint bp in blueprintsByStage[currentStageIndex])
            {
                bp.gameObject.SetActive(true);
            }

            UpdateUI();
        }
        else
        {
            Debug.Log("Сборка завершена!");
            onAllBlueprintsFilled.Invoke();

            BlueprintUIManager.Instance.SetUIActive(false);
        }
    }

    private void NotifyExamManager()
    {
        ExamManager.Instance?.IncrementDetailCount();
    }

    private void Start()
    {
        onAllBlueprintsFilled.AddListener(OnAllBlueprintsFilled);
    }

    private void OnAllBlueprintsFilled()
    {
        ExamManager.Instance?.EndExam();
    }

    // Метод для обновления UI при инициализации
    private void UpdateUI()
    {
        int completedDetails = GetCompletedDetailsInCurrentStage();
        int totalDetails = blueprintsByStage[currentStageIndex].Count;
        BlueprintUIManager.Instance.UpdateUI(totalStages, currentStageIndex + 1, completedDetails, totalDetails);
    }

    // Метод для получения количества заполненных деталей на текущем этапе
    private int GetCompletedDetailsInCurrentStage()
    {
        int count = 0;
        foreach (Blueprint bp in blueprintsByStage[currentStageIndex])
        {
            if (bp.IsFilled)
                count++;
        }

        return count;
    }
}using System.Collections.Generic;
using TMPro;
using UnityEngine;
using UnityEngine.EventSystems;
using UnityEngine.UI;

public class DraggableHandle : MonoBehaviour, IDragHandler, IBeginDragHandler, IEndDragHandler, IPointerEnterHandler, IPointerExitHandler
{
    public GameObject targetObject;
    private DraggableObject draggableObjectScript;
    public UIColorChanger colorChanger;
    private int ignoreLayer;
    public bool isDrag;
    private Camera camera;
    
    public TMP_Text detailNameText;
    public Image image;

    void Start()
    {
        camera = Camera.main;
        ignoreLayer = LayerMask.NameToLayer("Ignore Raycast");
        if (colorChanger == null)
        {
            colorChanger = GetComponent<UIColorChanger>();
        }
    }

    public void Init(DraggableObject draggableObject)
    {
        targetObject = draggableObject.gameObject;
        draggableObjectScript = draggableObject;
        GetComponent<ResizeBasedOnDistance>().Init(targetObject.transform);
        detailNameText.text = draggableObjectScript.dronePart.name;
        ShowUI(false);
    }

    public void OnBeginDrag(PointerEventData eventData)
    {
        if (eventData.button == PointerEventData.InputButton.Left)
        {
            draggableObjectScript.EnableRigidbody(false);
            targetObject.layer = ignoreLayer; // Устанавливаем слой для игнорирования
            colorChanger?.SetColor(colorChanger.pressedColor);
            isDrag = true;

            ShowUI(true);
        }
    }

    public void OnDrag(PointerEventData eventData)
    {
        if (eventData.button == PointerEventData.InputButton.Left)
        {
            Ray ray = camera.ScreenPointToRay(Input.mousePosition);
            RaycastHit hit;

            // Игнорируем слой Ignore Raycast
            int layerMask = ~LayerMask.GetMask("Ignore Raycast");

            if (Physics.Raycast(ray, out hit, Mathf.Infinity, layerMask))
            {
                // Проверяем, попал ли рейкаст в блюпринт
                Blueprint blueprint = hit.collider.GetComponent<Blueprint>();
                if (blueprint != null && blueprint.dronePart.name == draggableObjectScript.dronePart.name)
                {
                    // Заменяем блюпринт объектом
                    targetObject.transform.position = blueprint.transform.position;
                    targetObject.transform.rotation = blueprint.transform.rotation;
                    targetObject.transform.localScale = blueprint.transform.localScale;
                    Debug.Log("Объект заменил блюпринт.");
                }
                else
                {
                    // Перемещаем объект на позицию попадания рейкаста
                    Vector3 targetPosition = hit.point;

                    // Размеры коллайдера
                    Vector3 colliderExtents = targetObject.GetComponent<Collider>().bounds.extents;

                    // Смещение объекта назад по направлению луча
                    Vector3 offset = ray.direction * colliderExtents.z * 0.5f;
                    targetPosition -= offset;

                    // Поднимаем объект на высоту его половины
                    targetPosition.y += colliderExtents.y;

                    // Смещаем объект вбок на половину его ширины
                    targetPosition.x -= colliderExtents.x * 0.5f;

                    targetObject.transform.position = targetPosition;
                }
            }

            // Обновляем позицию UI элемента
            transform.position = Input.mousePosition;
        }
    }

    public void OnEndDrag(PointerEventData eventData)
    {
        if (eventData.button == PointerEventData.InputButton.Left)
        {
            Ray ray = camera.ScreenPointToRay(Input.mousePosition);
            RaycastHit hit;

            // Игнорируем слой Ignore Raycast
            int layerMask = ~LayerMask.GetMask("Ignore Raycast");

            if (Physics.Raycast(ray, out hit, Mathf.Infinity, layerMask))
            {
                Blueprint blueprint = hit.collider.GetComponent<Blueprint>();
                if (blueprint != null && blueprint.dronePart.name == draggableObjectScript.dronePart.name)
                {
                    // Оставляем объект на месте и удаляем ненужные компоненты
                    targetObject.transform.position = blueprint.transform.position;
                    targetObject.transform.rotation = blueprint.transform.rotation;
                    targetObject.transform.localScale = blueprint.transform.localScale;

                    // Destroy(targetObject.GetComponent<Collider>());
                    Destroy(targetObject.GetComponent<Rigidbody>());
                    Destroy(gameObject);
                    blueprint.Fill(); // Уведомляем о заполнении

                    Debug.Log("Объект закреплен на месте блюпринта.");
                    blueprint.gameObject.SetActive(false);
                    targetObject.layer = 0; // Возвращаем объект на стандартный слой
                    return;
                }
            }

            targetObject.layer = 0; // Возвращаем объект на стандартный слой
            draggableObjectScript.EnableRigidbody(true);
            colorChanger?.SetColor(colorChanger.normalColor);
            isDrag = false;

            ShowUI(false);
        }
    }

    public void OnPointerEnter(PointerEventData eventData)
    {
        if (!isDrag)
        {
            colorChanger?.SetColor(colorChanger.hoverColor);

            ShowUI(true);
        }
    }

    public void OnPointerExit(PointerEventData eventData)
    {
        if (!isDrag)
        {
            colorChanger?.SetColor(colorChanger.normalColor);
            ShowUI(false);
        }
    }

    public void ShowUI(bool value)
    {
        detailNameText.gameObject.SetActive(value);
    }
}using System;
using EasyButtons;
using UnityEngine;
using UnityEngine.UI;

public class DraggableObject : MonoBehaviour
{
    private GameObject handlePrefab;
    private GameObject handleInstance;
    private Rigidbody rb;
    [HideInInspector] public DronePart dronePart;
    private Collider objectCollider;
    private Camera camera;
    
    [HideInInspector]
    public RespawnHandler respawnHandler;

    void Awake()
    {
        if (handlePrefab == null)
        {
            handlePrefab = Resources.Load<GameObject>("Prefabs/handlePrefab");
            if (handlePrefab == null)
            {
                Debug.LogError("handlePrefab не найден в Resources/Prefabs/handlePrefab");
            }
        }

        respawnHandler = gameObject.AddComponent<RespawnHandler>();
    }

    void Start()
    {
        camera = Camera.main;
        rb = GetComponent<Rigidbody>();
        objectCollider = GetComponent<Collider>();
        dronePart = GetComponent<DronePart>();
        CreateHandle();
    }

    void Update()
    {
        if (handleInstance != null)
        {
            Vector3 screenPosition = camera.WorldToScreenPoint(transform.position);

            // Проверяем, находится ли объект перед камерой
            if (screenPosition.z > 0)
            {
                // Объект перед камерой, обновляем позицию UI-элемента
                handleInstance.transform.position = screenPosition;
                handleInstance.SetActive(true);
            }
            else
            {
                // Объект позади камеры, скрываем UI-элемент
                handleInstance.SetActive(false);
            }
        }
    }

    void CreateHandle()
    {
        if(handlePrefab != null)
        {
            handleInstance = Instantiate(handlePrefab, SceneSwither.Instance.sceneObjectParent.transform);

            Vector3 screenPosition = camera.WorldToScreenPoint(transform.position);
            handleInstance.transform.position = screenPosition;

            DraggableHandle handleScript = handleInstance.GetComponent<DraggableHandle>();
            handleScript.Init(this);
        }
    }

    public void EnableRigidbody(bool enable)
    {
        if (rb != null)
        {
            rb.isKinematic = !enable;
        }
    }

    public void EnableCollider(bool enable)
    {
        if (objectCollider != null)
        {
            objectCollider.enabled = enable;
        }
    }
}