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)
  {

  }
}

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

(0)

相关推荐

  • unity实现鼠标拖住3D物体

    本文实例为大家分享了unity实现鼠标拖住3D物体的具体代码,供大家参考,具体内容如下 把该脚本直接挂在要拖拽的物体上即可 using System.Collections; using System.Collections.Generic; using UnityEngine; public class ModelDrages : MonoBehaviour { //发射射线的摄像机 private Camera cam; //射线碰撞的物体 private GameObject go; //

  • Unity3D UGUI实现缩放循环拖动卡牌展示效果

    本文实例为大家分享了Unity3D UGUI实现缩放循环拖动卡牌展示的具体代码,供大家参考,具体内容如下 需求:游戏中展示卡牌这种效果也是蛮酷炫并且使用的一种常见效果,下面我们就来实现以下这个效果是如何实现. 思考:第一看看到这个效果,我们首先会想到UGUI里面的ScrollRect,当然也可以用ScrollRect来实现缩短ContentSize的width来自动实现重叠效果,然后中间左右的卡牌通过计算来显示缩放,这里我并没有用这种思路来实现,我提供另外一种思路,就是自己去计算当前每个卡牌的位

  • 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 Sy

  • Unity 从UI中拖拽对象放置并拖动效果 附demo

    需求:点击UI,在场景中生成3D对象,对象跟随鼠标移动,放置后可再次拖拽对象,改变其位置.做了一个小Demo,如下图所示: 实现大致思路: 射线碰撞检测 对象空间坐标变换(世界坐标->屏幕坐标.屏幕坐标->世界坐标) 首先为要生成3D对象的UI添加一个鼠标监听事件,脚本如下: SelectImage.cs using System.Collections; using System.Collections.Generic; using UnityEngine; using UnityEngin

  • Unity UI实现拖拽旋转

    本文实例为大家分享了Unity UI实现拖拽旋转的具体代码,供大家参考,具体内容如下 跟随鼠标旋转 第一种效果是跟随鼠标旋转,原理是计算下鼠标位置与拖拽物体的相对位移 旋转方向即可 注意转换对应空间坐标 新建脚本mono类继承 IBeginDragHandler, IDragHandler, IEndDragHandler 接口 [SerializeField] private Canvas m_Canvas; private Vector3? CalculateWorldToScreenPos

  • Unity工具类ScrollView实现拖拽滑动翻页

    简介: 在进行UI设计的时候,经常会使用Unity中UI提供的ScrollView,类似Android中的ScrollView,在进行图片预览,多个翻页的时候,能实现很好的效果. 该类中根据Unity的EventSystems中拖拽事件,实现对页码的滑动监听,在使用的时候,新建UI--->ScrollView,把该类组件添加到ScrollView上,把对应的content加入该脚本中的content,调整ScrollView和Content,设置单个滑动页的宽度,拖拽的阈值,即可监听到拖拽,如果

  • jquery ui sortable拖拽后保存位置

    jqueryUI sortable 可以用来进行页面拖拽布局,然而有一个小问题就是拖拽后如何保存状态. 工作中遇到了这个情况,遍把这个问题记了下来,具体思路是: 利用拖拽stop后利用 var arr = $( ".sortable" ).sortable('toArray'); 记录拖拽后的id数组顺序,然后把这个数组存起来,可以存cookie,数据库,localstorage等,刷新页面后读取这个数组,然后进行重新排序. 具体的代码如下可直接复制运行.本文将数组保存在localst

  • Javascript基于jQuery UI实现选中区域拖拽效果

    一.效果展示 普通的三个div 鼠标拖动选中效果 选中所有的div 这样貌似看不出效果,没关系,我们有神奇的gif动画,来一个整体的动画效果感受下. 二.代码实现 整个代码其实也不难,需要用到一个博主自己封装的js文件. AreaSelect.js 考虑到代码量有点大,并且知乎没有代码折叠功能,所以这里就留一个文件名.等博主抽时间将它开源到github上面去,当然,有需要的朋友也可以直接联系博主,博主免费提供! 引入这个js后,还需要引用jquery和jquery UI相关文件. <script

  • JQuery UI的拖拽功能实现方法小结

    JQuery UI提供的API极大简化了拖拽功能的开发.只需要分别在拖拽源(source)和目标(target)上调用draggable和droppable两个函数即可. 拖拽原理 首先要明确几个概念. ource:拖拽源,要拖动的元素. taerget:拖放目标,能够放入source的容器. 拖拽的动作分解如下: 1. drag start:在拖拽源(source)上按下鼠标并开始移动 2. drag move: 移动过程中 3. drag enter: 移动进入目标(target)容器 4.

  • Jquery UI实现一次拖拽多个选中的元素操作

    项目需要,实现一个拖放操作,要求每次可以拖拽选中的多个元素,释放到目标容器后可排序.考虑了一下,觉得jquery-ui比较合适,毕竟它提供了项目需要的交互性事件机制.拖拽.释放.排序.选择等效果.而在实际的操作中,遇到个很多的问题,说明一下,最后附上效果图和代码. 1.本人使用的bootstrap框架,引入jquery-ui后,为元素添加拖拽方法后,提示该方法不是一个函数.查找原因,是bootstrap和jquery-uide的$ 标识符控制权冲突.在引入的jquery-ui的js前加上一下语句

  • Unity UGUI实现简单拖拽图片功能

    这一篇博客我们来使用 UGUI 实现图片的拖拽功能. 说到拖拽,那必然离不开坐标,UGUI 的坐标有点不一样,它有两种坐标,一种是屏幕坐标,还有一种就是 UI 在Canvas内的坐标(暂时叫做ugui坐标.),这两个坐标是不一样的,所以拖拽是就需要转换.因为鼠标的移动是屏幕坐标,而 UI 的移动是ugui坐标.转换的方法: RectTransformUtility.ScreenPointToLocalPointInRectangle ( - );这个方法可以把屏幕坐标转换成 ugui 坐标.至于

  • 基于Cesium实现拖拽3D模型的示例代码

    目录 添加基站模型 拖拽 这个地方是想实现一个什么效果呢?就是使用 cesium 在地图上添加一个3D模型,然后实现拖拽效果. 添加基站模型 然后这篇博文介绍的主要不是添加模型,但是也简单把代码直接粘贴过来吧,就不详细说了. // 添加基站模型 function addSite() { let position = Cesium.Cartesian3.fromDegrees(116.236393, 40.075119, 0); // 设置模型方向 let hpRoll = new Cesium.

随机推荐