效果展示:
2D转3D视频
UI结构
UI组件挂载
UI结构
这个脚本挂载到 3D物体身上
csharp
using DG.Tweening;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class DragGame : MonoBehaviour
{
[HideInInspector]
public bool isDrag;
public int z=8;
void Start()
{
}
// Update is called once per frame
void Update()
{
}
IEnumerator OnMouseDown()
{
Vector3 screenSpace = Camera.main.WorldToScreenPoint(transform.position);//三维物体坐标转屏幕坐标
//将鼠标屏幕坐标转为三维坐标,再计算物体位置与鼠标之间的距离
var offset = transform.position - Camera.main.ScreenToWorldPoint(new Vector3(Input.mousePosition.x, Input.mousePosition.y, screenSpace.z));
isDrag = true;
while (Input.GetMouseButton(0))
{
Vector3 curScreenSpace = new Vector3(Input.mousePosition.x, Input.mousePosition.y, z);
var curPosition = Camera.main.ScreenToWorldPoint(curScreenSpace) + offset;
transform.position = curPosition;
yield return new WaitForFixedUpdate();
}
}
IEnumerator OnMouseUp()
{
isDrag = false;
Whereabouts();
yield return 0;
}
private void OnTriggerEnter(Collider other)
{
//物体拖出后 碰到其他物体的逻辑
}
public void Whereabouts()
{
RaycastHit hit;
//参数:当前物体,世界空间的方向,碰撞信息,最大距离
if (Physics.Raycast(transform.position, transform.TransformDirection(Vector3.down), out hit, Mathf.Infinity))
{
transform.DOMove(new Vector3(hit.point.x, hit.point.y + (transform.localScale.y / 2), hit.point.z), 0.5f);
}
}
}
挂载到UI上面
csharp
using DG.Tweening;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
public class KnapsackPanel : MonoBehaviour
{
List<GameObject> scrollList = new List<GameObject>();//容量列表
List<Toggle> toggles = new List<Toggle>();//背包类型列表
GameObject to, sv, im;
GameObject toggle;
GameObject scrollView;
Toggle Switch;
public void Start()
{
toggle = transform.Find("GameObject/ToggleGroup/Toggle").gameObject;
scrollView = transform.Find("GameObject/ScrollGroup/Scroll View").gameObject;
Switch = transform.Find("GameObject/BG/Switch").GetComponent<Toggle>();
RectTransform tf = transform.Find("GameObject").GetComponent<RectTransform>();
Switch.onValueChanged.AddListener((arg) =>
{
if (arg)
{
tf.transform.DOLocalMoveX(tf.transform.localPosition.x - tf.rect.width, 1f);
}
else
{
tf.transform.DOLocalMoveX(tf.transform.localPosition.x + tf.rect.width, 1f);
}
});
CreateKnapsack();
}
/// <summary>
/// 生成背包内容
/// </summary>
public void CreateKnapsack()
{
Toggle[] tog = transform.Find("GameObject/ToggleGroup").GetComponentsInChildren<Toggle>();
for (int i = 0; i < tog.Length; i++)
{
toggles.Add(tog[i]);
}
ScrollRect[] scrollbars= transform.Find("GameObject/ScrollGroup").GetComponentsInChildren<ScrollRect>(true);
for (int i = 0; i < scrollbars.Length; i++)
{
scrollList.Add(scrollbars[i].gameObject);
Transform content = scrollbars[i].transform.Find("Viewport/Content");
for (int j = 0; j < content.childCount; j++)
{
int t = j;
GameObject game = Resources.Load<GameObject>(content.GetChild(t).name);//需要拖拽出的3D物体
DragGameCommand drag = new DragGameCommand(content.GetChild(t).gameObject, game, j, () => { Switch.isOn = true; });
//dragGames.Add(drag);
}
}
//类型切换事件绑定
for (int i = 0; i < toggles.Count; i++)
{
int t = i;
toggles[i].onValueChanged.RemoveAllListeners();
toggles[i].onValueChanged.AddListener((arg) =>
{
scrollList[t].SetActive(arg);
});
}
}
}
挂载到空物体上
csharp
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class IEnumeratorManager : MonoBehaviour
{
public static IEnumeratorManager instance;
void Start()
{
instance = this;
}
}
这个脚本 不需要挂载
csharp
using System;
using System.Collections;
using System.Collections.Generic;
using System.Threading.Tasks;
using UnityEngine;
using UnityEngine.EventSystems;
using UnityEngine.UI;
public class DragGameCommand
{
public GameObject instance;//UI图标
public GameObject dragGame;//拖拽的物体
GameObject game;//要创建的物体
public GameObject scrollView;//对应的背包分类界面(拖回物体到UI的范围)
public int z;//物体的Z轴距离
int index;//在背包里排列的索引
Action dragEnd;
public DragGameCommand(GameObject image, GameObject _game, int _index, Action _dragEnd)
{
instance = image;
game = _game;
scrollView = image.transform.parent.parent.parent.gameObject;
AddListener();
z = 8;
int index = _index;
dragEnd = _dragEnd;
AddEvent(scrollView.transform);
}
#region 背包拖出物体
/// <summary>
/// 物体从UI 拖出的事件
/// </summary>
private void AddListener()
{
//给Image 动态添加 拖拽 事件
EventTrigger eventTrigger = instance.gameObject.AddComponent<EventTrigger>();
EventTrigger.Entry beginDrag = new EventTrigger.Entry();
beginDrag.eventID = EventTriggerType.BeginDrag;
beginDrag.callback.AddListener((v) =>
{
Debug.Log("开始拖拽");
Image dragImage = instance.GetComponent<Image>();
dragImage.raycastTarget = false;//UI置灰
dragImage.color = new Color(1, 1, 1, 0.5f);
string name = game.name;
dragGame = GameObject.Instantiate(game);//创建3D物体
DragGame dg = dragGame.GetComponent<DragGame>();
dg.z = z;
dragGame.name = name;
ObjFollowMouse(dragGame);//让物体跟随鼠标
});
EventTrigger.Entry drag = new EventTrigger.Entry();
drag.eventID = EventTriggerType.Drag;
drag.callback.AddListener((v) =>
{
ObjFollowMouse(dragGame);//让物体跟随鼠标
});
EventTrigger.Entry endDrag = new EventTrigger.Entry();
endDrag.eventID = EventTriggerType.EndDrag;
endDrag.callback.AddListener((v) => {
dragEnd?.Invoke();
dragGame.GetComponent<DragGame>().Whereabouts();//下落
});
eventTrigger.triggers.Add(beginDrag);
eventTrigger.triggers.Add(drag);
eventTrigger.triggers.Add(endDrag);
}
/// <summary>
/// UI跟随鼠标
/// </summary>
/// <param name="eventData"></param>
private void ObjFollowMouse(GameObject gameObject)
{
gameObject.transform.position = Camera.main.ScreenToWorldPoint(Input.mousePosition + new Vector3(0, 0, z));
}
#endregion
#region 物体放回背包
Coroutine coroutine;
//绑定背包界面鼠标移入和移出事件
public void AddEvent(Transform viewport)
{
EventTrigger eventr = viewport.gameObject.AddComponent<EventTrigger>();//给拖入范围UI,添加 鼠标进入和鼠标离开事件
EventTrigger.Entry pointerEnter = new EventTrigger.Entry();
pointerEnter.eventID = EventTriggerType.PointerEnter;
pointerEnter.callback.RemoveAllListeners();
//鼠标进入UI
pointerEnter.callback.AddListener((v) =>
{
if (dragGame != null)//已经拖出来的物体
{
DragGame dragGame1 = dragGame.GetComponent<DragGame>();
if (dragGame1.isDrag)//物体正在拖拽中
{
coroutine =IEnumeratorManager.instance. StartCoroutine(OnMouse(index));//放回背包事件
}
}
});
EventTrigger.Entry pointerExit = new EventTrigger.Entry();
pointerExit.eventID = EventTriggerType.PointerExit;
pointerExit.callback.RemoveAllListeners();
//鼠标离开UI
pointerExit.callback.AddListener((v) =>
{
if (coroutine != null)
{
IEnumeratorManager.instance.StopCoroutine(coroutine);
}
});
eventr.triggers.Add(pointerEnter);
eventr.triggers.Add(pointerExit);
}
/// <summary>
/// 物体放回背包
/// </summary>
/// <param name="index"></param>
/// <returns></returns>
IEnumerator OnMouse(int index)
{
DragGame game = dragGame.GetComponent<DragGame>();
Image image = instance.GetComponent<Image>();
while (true)
{
if (!game.isDrag && scrollView.activeInHierarchy)//物体结束拖拽 并且在对应的背包类型容量处于显示状态、
{
GameObject.DestroyImmediate(game.gameObject);
image.raycastTarget = true;
image.color = new Color(1, 1, 1, 1);
dragGame = null;
IEnumeratorManager.instance. StopCoroutine(coroutine);
}
yield return 0;
}
}
#endregion
}
可以根据自己需求去修改,比如 动态生成背包里的类型和元素,
Demo上传了,可以下载,