当前位置: 首页 > news >正文

unity点击button后不松开通过拖拽显示模型松开后模型实例化

using System.Collections;
using UnityEngine;
using UnityEngine.EventSystems;
using UnityEngine.UI;

[RequireComponent(typeof(Button))] // 确保脚本挂在Button上
public class DragButtonSpawner : MonoBehaviour, IPointerDownHandler, IDragHandler, IPointerUpHandler
{
    [Header("拖拽设置")]
    [Tooltip("模型预制体路径前缀")]
    public string modelPathPrefix = "ModePrefab/"; // 模型资源路径前缀

    [Tooltip("允许放置的层级")]
    public LayerMask allowedLayers = ~0; // 默认所有层级

    [Tooltip("放置偏移量")]
    public Vector3 placementOffset = Vector3.zero; // 模型放置时的位置偏移

    private GameObject currentDraggingModel; // 当前正在拖拽的模型
    private bool isDragging = false;        // 是否正在拖拽
    private string modelName;               // 模型名称缓存

    void Awake()
    {
        // 缓存按钮名称作为模型名称
        // 移除可能的"(Clone)"后缀
      
    }

    // 按钮按下时 - 开始拖拽
    public void OnPointerDown(PointerEventData eventData)
    {
        // 异步加载模型避免卡顿
        StartCoroutine(LoadAndInitModel());
    }

    // 异步加载模型
    private IEnumerator LoadAndInitModel()
    {
        modelName = this.name.Replace("(Clone)", "").Trim();
        Debug.Log(modelName);
        ResourceRequest request = Resources.LoadAsync<GameObject>(modelPathPrefix + modelName);
        yield return request;

        Debug.Log(request.asset.name);
        if (request.asset == null)
        {
            Debug.LogError($"加载模型失败: {modelPathPrefix}{modelName}");
            yield break;
        }

        // 实例化模型但不显示
        currentDraggingModel = Instantiate(request.asset) as GameObject;
       // currentDraggingModel.name = modelName + "_Instance";
        currentDraggingModel.name = modelName;
        currentDraggingModel.SetActive(false);
        isDragging = true;
    }

    // 拖拽过程中 - 更新模型位置
    public void OnDrag(PointerEventData eventData)
    {
        if (!isDragging || currentDraggingModel == null) return;

        Ray ray = Camera.main.ScreenPointToRay(eventData.position);
        RaycastHit hit;

        // 只在指定层级上检测碰撞
        if (Physics.Raycast(ray, out hit, Mathf.Infinity, allowedLayers))
        {
            // 显示模型并更新位置(添加偏移量)
            currentDraggingModel.SetActive(true);
            currentDraggingModel.transform.position = hit.point + placementOffset;
            GameObject terrain = GameObject.Find("Terrain");
            currentDraggingModel.transform.parent = terrain.transform;
            // 使模型朝向法线方向(可选)
            currentDraggingModel.transform.rotation = Quaternion.FromToRotation(Vector3.zero, hit.normal);
        }
        else
        {
            currentDraggingModel.SetActive(false);
        }
    }

    // 按钮释放时 - 完成放置或取消
    public void OnPointerUp(PointerEventData eventData)
    {
        if (!isDragging || currentDraggingModel == null) return;

        if (currentDraggingModel.activeSelf)
        {
            FinalizePlacement();
        }
        else
        {
            CancelPlacement();
        }

        ResetDragState();
    }

    // 最终确认放置
    private void FinalizePlacement()
    {
        // 添加放置音效(可选)
        // AudioManager.PlayPlacementSound();

        // 移除临时组件或添加持久化组件
        //var tempCollider = currentDraggingModel.GetComponent<TemporaryCollider>();
        //if (tempCollider != null) Destroy(tempCollider);

        //Debug.Log($"模型 {modelName} 已放置在场景中");
    }

    // 取消放置
    private void CancelPlacement()
    {
        Destroy(currentDraggingModel);
        Debug.Log("拖拽已取消");
    }

    // 重置拖拽状态
    private void ResetDragState()
    {
        currentDraggingModel = null;
        isDragging = false;
    }

    // 当脚本禁用时确保清理
    void OnDisable()
    {
        if (isDragging && currentDraggingModel != null)
        {
            CancelPlacement();
            ResetDragState();
        }
    }
}
http://www.dtcms.com/a/108046.html

相关文章:

  • 【工业场景】用YOLOv12实现饮料类别识别
  • 基于神经网络的肾脏疾病预测模型
  • 单元测试原则之——不要模拟不属于你的类型
  • 亚马逊云科技赋能英矽智能,打破新药研发“双十”定律
  • VASP计算过渡态(CI-NEB)初始结构生成脚本汇总
  • 【MySQL篇】limit深度分页性能:从原理理解小偏移量limit 1,200 vs 百万级偏移量limit 1000000,200的差异
  • DirectX安装及使用教程(附安装包)
  • MongoDB安装完整教程
  • Transformer【学习记录】
  • react使用eventBus在不同模块间进行通信
  • Synology NAS 部署WPS-Office
  • zk基础—3.集群与核心参数二
  • 2025年优化算法:真菌生长优化算法(Fungal Growth Optimizer,FGO)
  • 【NetCore】ControllerBase:ASP.NET Core 中的基石类
  • 长短期记忆神经网络(LSTM)基础学习与实例:预测序列的未来
  • 外卖平台问题
  • 未来幻想世界
  • JAVA学习小计之IO流01-字节流篇
  • Axure 使用笔记
  • leetcode:3083. 字符串及其反转中是否存在同一子字符串(python3解法)
  • 算法设计与分析之“分治法”
  • Oracle常用高可用方案(10)——RAC
  • MFC BCGControlBar
  • 光谱相机的光谱数据采集原理
  • Python设计模式:代理模式
  • 看行业DeepSeekR1模型如何构建及减少推理大模型过度思考
  • IntelliJ IDEA全栈Git指南:从零构建到高效协作开发
  • 洛谷题单3-P1009 [NOIP 1998 普及组] 阶乘之和-python-流程图重构
  • vue中的 拖拽
  • @ComponentScan注解详解:Spring组件扫描的核心机制