Unity UI拖拽模型选择功能

 更新时间:2020年01月07日 11:53:25   作者:迷走逃走  
这篇文章主要为大家详细介绍了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)
  {

  }
}

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持脚本之家。

相关文章

  • c# 如何实现代码生成器

    c# 如何实现代码生成器

    这篇文章主要介绍了c# 如何实现代码生成器,帮助大家更好的理解和使用c# 编程语言,感兴趣的朋友可以了解下
    2020-12-12
  • C#中ListView控件实现窗体代码

    C#中ListView控件实现窗体代码

    这篇文章主要介绍了C#中ListView控件实现窗体的核心代码,非常不错,具有参考借鉴价值,对c#listview相关知识感兴趣的朋友一起学习吧
    2016-08-08
  • C#使用NPOI实现Excel和DataTable的互转

    C#使用NPOI实现Excel和DataTable的互转

    这篇文章主要为大家详细介绍了C#使用NPOI实现Excel和DataTable的互转,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2022-02-02
  • C#代替go采用的CSP并发模型实现

    C#代替go采用的CSP并发模型实现

    这篇文章主要为大家介绍了C#代替go采用的CSP并发模型的轻松实现,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步早日升职加薪
    2022-04-04
  • 如何使用正则表达式判断邮箱(以C#为例)

    如何使用正则表达式判断邮箱(以C#为例)

    在C#中可以使用Regex正则表达式类来校验前台提交过来的邮箱字段信息是否符合要求,Regex类是C#中有关正则表达式处理的相关类,功能强大,下面这篇文章主要给大家介绍了关于如何使用正则表达式判断邮箱的相关资料,需要的朋友可以参考下
    2022-03-03
  • C#委托与冒泡排序实例

    C#委托与冒泡排序实例

    这篇文章介绍了C#委托与冒泡排序的实例,文中通过示例代码介绍的非常详细。对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
    2022-04-04
  • C#中TextBox实现输入提示功能的方法

    C#中TextBox实现输入提示功能的方法

    这篇文章主要介绍了C#中TextBox实现输入提示功能的方法,涉及C#中TextBox的相关操作技巧,需要的朋友可以参考下
    2015-06-06
  • C#实现DataTable转换成IList的方法

    C#实现DataTable转换成IList的方法

    这篇文章主要介绍了C#实现DataTable转换成IList的方法,涉及C#针对DataTable操作的相关技巧,需要的朋友可以参考下
    2016-03-03
  • C#使用IronPython调用Python

    C#使用IronPython调用Python

    这篇文章主要给大家介绍了关于C#使用IronPython调用Python的相关资料, c#利用IronPython调用python的过程中总会遇到种种问题,这里给大家总结下,需要的朋友可以参考下
    2023-07-07
  • WPF实现好看的Loading动画的示例代码

    WPF实现好看的Loading动画的示例代码

    这篇文章主要介绍了如何利用WPF实现好看的Loading动画效果,文中的示例代码讲解详细,对我们学习或工作有一定帮助,需要的可以参考一下
    2022-08-08

最新评论