Unity UI拖拽模型选择

指定一块区域,玩家鼠标or手指拖拽这个区域,模型会进行偏移,并用于进行人物、道具的选择

给模型定义一些属性


using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class UIModelUtil : MonoBehaviour
{
    public Animator animator;
    public int id;
    public int index;

}

模型控制

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class UIModelControl : MonoBehaviour
{
    public Transform modelsParent;
    public Transform centerPos;
    public float interval;
    public  bool loop;

    List<UIModelUtil> models;
    bool isPressing;
    public UIDrag dragComp;


    Vector3 mousePos;

    private void Awake()
    {
        if(models == null)
        {
            int i = 0;
            models = new List<UIModelUtil>();
            foreach(UIModelUtil util in modelsParent.GetComponentsInChildren<UIModelUtil>())
            {
                models.Add(util);
                //util.index = i;
                Vector3 pos = Vector3.zero;
                pos.x = i * interval;
                util.transform.localPosition = pos;
                i++;
            }
        }
    }

    private void Start()
    {
        JumpToSelect();
    }

    
    private void Update()
    {
        //接受拖拽事件
        if (isPressing)
        {
            float x = GetInputDeltaX();
            int dir = 0;
            if (x > 0) dir = 1;
            else if (x < 0) dir = -1;

            //分辨率修正
            if (dir == 0) return;
            x = Mathf.Abs(x) / (Screen.width) * 800f;
            if (x > 800f) x = 800f;

            //偏移
            float currectX = Mathf.Lerp(0, interval, x / 800f) * dir;
            Vector3 pos = modelsParent.position;
            pos.x += currectX;



                Transform right = GetRight().transform;
                Transform left = GetLeft().transform;
            //不循环时候设置边框
            if (models.Count > 2 || !loop || models.Count == 1)
            {
        

                if (right.localPosition.x + interval / 10 < -pos.x) pos.x = -(right.localPosition.x + interval / 10);
                else if (left.localPosition.x - interval / 10 > -pos.x) pos.x = -(left.localPosition.x - interval / 10);

                //modelsParent.position = pos;
            }
            //只有两个循环的时候
            else if (models.Count == 2 && loop)
            {

                Transform selected = GetSelect().transform;
                //当前是右边那个且向右拖拽
                if (selected == right && dir < 0)
                {
                    
                    Vector3 leftPos = left.localPosition;
                    leftPos.x = right.localPosition.x + interval;
                    left.localPosition = leftPos;
                }
                //当前是左边那个且向左拖拽
                else if (selected == left && dir > 0)
                {
                    Vector3 rightPos = right.localPosition;
                    rightPos.x = left.localPosition.x - interval;
                    right.localPosition = rightPos;
                }
            }
            modelsParent.position = pos;
            
            AfterSelect();
        }
    }


    void AfterSelect()
    {
        foreach(UIModelUtil util in models)
        {
            float dis = GetXDis(util);
            //设置显示
            if (dis > interval)
                util.gameObject.SetActive(false);
            else
            { 
                //越靠近中间越前
                util.gameObject.SetActive(true);
                float t = Mathf.Abs(dis) / interval;
                float y = Mathf.Lerp(centerPos.position.z, modelsParent.position.z, t);
                Vector3 pos = util.transform.position;
                pos.z = y;
                util.transform.position = pos;
            }

        }
        //循环时候位置修正
        if (loop && models.Count > 2)
        {
            Transform right = GetRight().transform;
            Transform left = GetLeft().transform;
            Transform selected = GetSelect().transform;
            if (selected == right)
            {
                Vector3 pos = right.position;
                pos.x += interval;
                left.position = pos;
            }
            else if (selected == left)
            {
                Vector3 pos = left.position;
                pos.x -= interval;
                right.position = pos;
            }
        }
        //设置UI选中状况
        dragComp.OnSelected(GetSelect().id, GetSelect().index);
    }

    //通过id选中
     UIModelUtil GetById(int id)
    {
        if (models == null) return null;
        UIModelUtil target = null;

        foreach (UIModelUtil util in models)
        {
            if (util.id == id) return util;
        }
        return target;
    }

    //获取当前选中
     UIModelUtil GetSelect()
    {
        if (models == null) return null;
        float min = 9999;

        UIModelUtil target = null;

        foreach(UIModelUtil util in models)
        {
            float dis = Mathf.Abs( GetXDis(util));
            if(dis < min)
            {
                target = util;
                min = dis;
            }
        }
        return target;
    }

    //所有模型最右边的那个
     UIModelUtil GetRight()
    {
        if (models == null) return null;
        float max = -9999;

        UIModelUtil target = null;

        foreach(UIModelUtil util in models)
        {
            float dis = util.transform.localPosition.x;
            if(dis > max)
            {
                target = util;
                max = dis;
            }
        }

        return target;
    }

    //所有模型最左边的那个
     UIModelUtil GetLeft()
    {
        if (models == null) return null;
        float min = 9999;

        UIModelUtil target = null;

        foreach(UIModelUtil util in models)
        {
            float dis = util.transform.localPosition.x;
            if(dis < min)
            {
                target = util;
                min = dis;
            }
        }


        return target;
    }

    //UI控件按下触发
    public void OnPress()
    {
        if (isPressing) return;
        isPressing = true;

        if (Application.isEditor)
            mousePos = Input.mousePosition;
        else
            mousePos = Input.GetTouch(0).position;
        if (backing != null) StopCoroutine(backing);
    }

    //UI控件释放触发
    public void OnRelease()
    {
        backing = StartCoroutine(ToSelect());
        isPressing = false;
    }


    Coroutine backing;
    //释放后偏移
    IEnumerator ToSelect()
    {


        UIModelUtil selected = GetSelect();
        float dis = GetXDis(selected);
        float time = Mathf.Lerp (0, 1f, Mathf.Abs(dis) / interval);
        float timer = 0;
        Vector3 from = modelsParent.localPosition;
        Vector3 to = from;
        to.x = -selected.transform.localPosition.x;

        while(timer < time)
        {
            timer += Time.deltaTime;
            float t = timer / time;
            Vector3 pos = Vector3.Lerp(from, to, t);
            modelsParent.localPosition = pos;
            AfterSelect();
            yield return null;
        }
        backing = null;

    }

    //获取手指偏移量
    float GetInputDeltaX()
    {
        Vector3 pos;
        if (Application.isEditor)
            pos = Input.mousePosition;
        else
            pos = Input.GetTouch(0).position;
        Vector3 delta = pos - mousePos;
        //Debug.Log(pos +"/"+mousePos +"/"+ delta.x);
        mousePos = pos;
        return delta.x;
            
    }

    //计算偏移中心位置的X轴距离
    float GetXDis(UIModelUtil util)
    {
        return util.transform.position.x - centerPos.position.x;
    }

    // 跳转到选中的id
    public void JumpToSelect()
    {
        int id = CharacterManager.characterId;
        Vector3 pos = modelsParent.localPosition;
        UIModelUtil selected = GetById(id);
        pos.x = -selected.transform.localPosition.x;
        modelsParent.localPosition = pos;

        AfterSelect();
    }





}

UI接受点击事件:

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.EventSystems;
public class UIDrag : MonoBehaviour,IPointerDownHandler, IPointerUpHandler
{
    public UIModelControl control;

    virtual public void OnPointerDown(PointerEventData data)
    {
        control.OnPress();
    }

    virtual public void OnPointerUp(PointerEventData data)
    {
        control.OnRelease();
    }

    virtual public void OnSelected(int id, int index)
    {

    }
}
  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
您好! 在Unity中创建3D物体并在UI拖拽出它可以通过以下步骤实现: 1. 创建一个3D物体,并将其命名为"3DObject"。 2. 在Hierarchy面板中选择"3DObject",然后在Inspector面板中将"Tag"设置为"Draggable"。 3. 在Hierarchy面板中创建一个UI > Button游戏对象,并将其命名为"DraggableButton"。 4. 在Project面板中创建一个新的C#脚本,并将其命名为"DraggableObject"。 5. 将"DraggableObject"脚本拖放到"3DObject"游戏对象上。 6. 在"DraggableObject"脚本中,添加以下代码: ``` using System.Collections; using System.Collections.Generic; using UnityEngine; using UnityEngine.EventSystems; public class DraggableObject : MonoBehaviour, IBeginDragHandler, IDragHandler, IEndDragHandler { public Transform parentToReturnTo = null; public Transform placeholderParent = null; GameObject placeholder = null; public void OnBeginDrag(PointerEventData eventData) { placeholder = new GameObject(); placeholder.transform.SetParent( this.transform.parent ); LayoutElement le = placeholder.AddComponent<LayoutElement>(); le.preferredWidth = this.GetComponent<LayoutElement>().preferredWidth; le.preferredHeight = this.GetComponent<LayoutElement>().preferredHeight; le.flexibleWidth = 0; le.flexibleHeight = 0; placeholder.transform.SetSiblingIndex( this.transform.GetSiblingIndex() ); parentToReturnTo = this.transform.parent; placeholderParent = parentToReturnTo; this.transform.SetParent( this.transform.parent.parent ); GetComponent<CanvasGroup>().blocksRaycasts = false; } public void OnDrag(PointerEventData eventData) { this.transform.position = eventData.position; if(placeholder.transform.parent != placeholderParent) placeholder.transform.SetParent(placeholderParent); int newSiblingIndex = placeholderParent.childCount; for(int i=0; i < placeholderParent.childCount; i++) { if(this.transform.position.x < placeholderParent.GetChild(i).position.x) {
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值