Unity拖拽物体到另外一个物体中的检测相关脚本(萝卜和坑)
来源:互联网 发布:数据恢复精灵如何使用 编辑:程序博客网 时间:2024/04/27 21:16
从前。。。有个兔子要把得来的几个萝卜埋到坑里面,现在就是检测萝卜埋坑里的方法,讲一下需求:
1.鼠标拖动萝卜可以放进不同的坑中。
2.当萝卜没有拖到坑中时就返回到原来位置
3.当萝卜拖到坑里时萝卜就放进坑里。
我是用TriggerEvent来检测的,顺便做了一些逻辑,语言描述不够好,还是上代码吧:
using UnityEngine;/// <summary>/// 拖拽接口/// </summary>public interface IDrag{ /// <summary> /// 开始拖动 /// </summary> void OnStartDrag(); /// <summary> /// 拖动中 /// </summary> void OnDrag(); /// <summary> /// 放下 /// </summary> void OnDrop();}/// <summary>/// 事件监听处理/// </summary>public interface IDispatch{ /// <summary> /// 添加事件监听 /// </summary> void AddEvent(); /// <summary> /// 移除对事件的监听 /// </summary> void RemoveEvent();}
上面是接口,用来描述我拖动中需要做的事情,下面是实现:
using System.Collections;using System.Collections.Generic;using UnityEngine;public class DraggerImpler : IDrag{ private GameObjDrag host; public DraggerImpler(GameObjDrag _host) { host = _host; } public void OnStartDrag() { host.IsDraging = true; } public void OnDrag() { host.IsDraging = true; } public void OnDrop() { host.IsDraging = false; if (host.IsReturn) { host.targetTransform.position = host.startTransform.position; } else { host.targetTransform.position = host.currTransform.position; } }}
上面这个脚本实现了Idrag 接口,因为没想到开始拖和正在拖需要做什么就先不管他,当放下的时候我做了个判断就是这个:
public void OnDrop() { host.IsDraging = false; if (host.IsReturn) { host.targetTransform.position = host.startTransform.position; } else { host.targetTransform.position = host.currTransform.position; } }
大概意思是如果需要返回了就把初始记录的位置给targetTransform,如果不需要返回就把currTransform的位置给targetTransform.
下面这个脚本是用来做碰撞检测后事件处理,萝卜进坑是和萝卜出坑时需要进行的逻辑写在这里。
这里有另外一个新需求:
当这个坑被萝卜占了,其他萝卜不能再进入这个坑
解决方案:所以给我在萝卜坑加了一个标记,当萝卜离开坑的时候就把这个标记移除。
出现问题:我怎么知道我移除的是自己的标记?
解决方案:给每个标记一个唯一的ID,根据ID来确定是不是自己加的标记
出现问题:当两个坑离得特别近的时候,从这个坑移动到另外一个坑的时候,会先触发一次进入下个坑的进入
事件,然后再触发这个坑的离开事件,导致我记录的ID被修改成新的坑的ID,导致我没办法移除我离开的那个坑的标记。(这个坑就没有萝卜,而且也不能再把萝卜放进去了)。
解决方案:把标记做一个列表List,当进入坑的时候往标记列表里加一个ID,当离开坑时就从列表里查是否有要离开这个坑的ID,有的话移除这个坑的标记,并且从列表里移除这个ID*
using System.Collections.Generic;using UnityEngine;public class TriggerImpler : IDispatch{ /// <summary> /// 监听到后对Obj进行操作 /// </summary> GameObjDrag _obj; /// <summary> /// 触发器的事件监听 /// </summary> TriggerEvent _te; /// <summary> /// 标记ID列表 /// </summary> List<int> _markIDs; public TriggerImpler(GameObjDrag obj) { _te = TriggerEvent.AddComponentToGameObject(obj.gameobject); _obj = obj; _markIDs = new List<int>(); } public void AddEvent() { _te.TriggerEnter += OnEnter; _te.TriggerExit += OnExit; } public void RemoveEvent() { _te.TriggerEnter -= OnEnter; _te.TriggerExit -= OnExit; } public void OnExit(GameObject obj) { //如果这个标记是自己加的才可以移除,不是自己加的不移除 Mark ma = obj.GetComponent<Mark>(); if (ma != null) { if (_markIDs.Contains(ma.GetInstanceID())) { UnityEngine.GameObject.Destroy(ma); _markIDs.Remove(ma.GetInstanceID()); } } //如果退出的obj不是当前记录的obj就不返回 if (_obj.currTransform.position == obj.transform.position) { _obj.IsReturn = true; _obj.currTransform.position = Vector3.zero; } } public void OnEnter(GameObject obj) { //如果进入的这个Obj被标记了,那么不赋值,如果没被标记,那么标记Obj,并且赋值 Mark ma = obj.GetComponent<Mark>(); if (ma == null) { ma = obj.AddComponent<Mark>(); //_markID = ma.GetInstanceID(); _markIDs.Add(ma.GetInstanceID()); _obj.IsReturn = false; _obj.currTransform.position = obj.transform.position; } }}
using System;using UnityEngine;public class TriggerEvent : MonoBehaviour { public Action<GameObject> TriggerEnter; public Action<GameObject> TriggerExit; /// <summary> /// 往一个物体上添加这个事件监听类 /// </summary> /// <param name="obj"></param> /// <returns></returns> public static TriggerEvent AddComponentToGameObject(GameObject obj) { TriggerEvent com = obj.GetComponent<TriggerEvent>(); if (com == null) { com = obj.AddComponent<TriggerEvent>(); } return com; } public void OnTriggerEnter(Collider other) { //Debug.Log("TriggerEnter" + other.gameObject.name); TriggerEnter(other.gameObject); } public void OnTriggerExit(Collider other) { //Debug.Log("TriggerExit" + other.gameObject.name); TriggerExit(other.gameObject); }}
上面这个脚本时用来做碰撞检测的,注意要给萝卜加刚体(rigidbody)和碰撞器(collider),坑只加碰撞器(collider)就好了,把碰撞器的isTrigger勾选。
做标记的脚本:
using System.Collections;using System.Collections.Generic;using UnityEngine;/// <summary>/// 用来做标记的一个脚本/// </summary>public class Mark : MonoBehaviour { /// <summary> /// 不允许用户手动修改,测试时看ID /// </summary> public int ID; // Use this for initialization void Start () { ID = GetInstanceID(); //Debug.Log(gameObject.name + " 这个物体已被标记,ID是 " + ID); } // Update is called once per frame void Update () { } public void OnDestroy() { //Debug.Log(gameObject.name + " 标记已经移除"); }}
恩恩下面是重点:
using UnityEngine;public class GameObjDrag{ public Position startTransform; public Position currTransform; public Position targetTransform; private bool _isReturn; /// <summary> /// 是否返回原位,true是返回,false是不返回 /// </summary> public bool IsReturn { get { return _isReturn; } set { _isReturn = value; } } private bool isDraging; /// <summary> /// 是否正在拖拽 /// </summary> public bool IsDraging { get { return isDraging; } set { isDraging = value; } } /// <summary> /// 拖拽的接口 /// </summary> public IDrag _dragInterface; /// <summary> /// 事件接口 /// </summary> public IDispatch _dispatchInterface; /// <summary> /// 被拖拽的物体 /// </summary> public GameObject gameobject; public GameObjDrag(GameObject obj) { gameobject = obj; startTransform = new Position(obj.transform.position,obj.transform.eulerAngles,obj.transform.localScale); currTransform = new Position(); targetTransform = new Position(); _isReturn = true; _dragInterface = new DraggerImpler(this); _dispatchInterface = new TriggerImpler(this); _dispatchInterface.AddEvent(); } public void SetDraggerImp(IDrag dragger) { _dragInterface = dragger; } public void SetTriggerImp(IDispatch trigger) { _dispatchInterface = trigger; } public void OnStartDrag() { _dragInterface.OnStartDrag(); } public void OnDrag() { _dragInterface.OnDrag(); } public void OnDrop() { _dragInterface.OnDrop(); }}/// <summary>/// 位置/// </summary>public class Position{ /// <summary> /// 位置 /// </summary> public Vector3 position; /// <summary> /// 旋转 /// </summary> public Vector3 rotation; /// <summary> /// 大小 /// </summary> public Vector3 scale; public Position(Vector3 pos, Vector3 rot, Vector3 sca) { position = pos; rotation = rot; scale = sca; } public Position() { position = Vector3.zero; rotation = Vector3.zero; scale = Vector3.zero; }}
using System.Collections;using System.Collections.Generic;using UnityEngine;public class EPGameObj : MonoBehaviour{ GameObjDrag ep; void Start() { ep = new GameObjDrag(this.gameObject); // ep.SetDragImp(new DraggerImpler(ep)); } IEnumerator OnMouseDown() { ep.OnStartDrag(); //将物体由世界坐标系转换为屏幕坐标系 Vector3 screenSpace = Camera.main.WorldToScreenPoint(transform.position); //完成了两个步骤,1由于鼠标的坐标系是2维的,需要转化成3维的世界坐标系 Vector3 mouseScreenSpace = new Vector3(Input.mousePosition.x, Input.mousePosition.y, screenSpace.z); //2只有三维的情况下才能来计算鼠标位置与物体的距离,offset即是距离 Vector3 offset = transform.position - Camera.main.ScreenToWorldPoint(mouseScreenSpace); while (Input.GetMouseButton(0))//鼠标左键被持续按下。 { ep.OnDrag(); //得到现在鼠标的2维坐标系位置 Vector3 curScreenSpace = new Vector3(Input.mousePosition.x, Input.mousePosition.y, screenSpace.z); //将当前鼠标的2维位置转换成3维位置 Vector3 curPosition = Camera.main.ScreenToWorldPoint(curScreenSpace) + offset; //curPosition就是物体应该的移动向量赋给transform的position属性 transform.position = curPosition; yield return new WaitForFixedUpdate(); } } public void OnMouseUp() { ep.OnDrop(); transform.position = ep.targetTransform.position; } void Dispose() { //记得remove拖拽碰撞检测事件 ep._dispatchInterface.RemoveEvent(); }}
上面这脚本就是我们要拖的萝卜上面需要挂的脚本,主要控制萝卜的移动和,松开鼠标时把重点位置修改一下。。。
- Unity拖拽物体到另外一个物体中的检测相关脚本(萝卜和坑)
- unity之RotateAround 一个物体围绕另外一个物体旋转
- Unity 拖拽物体的脚本
- 【Unity】动态生成物体,设置一个物体为另外一个物体的父类
- Unity通过脚本实现给一个物体添加子物体
- 拖拽物体脚本
- Unity物体跟随脚本
- DPM物体检测相关
- Unity鼠标拖拽物体
- unity 物体拖拽移动
- unity-transform(物体上升脚本)
- 场景中一个物体能否进入另外一个物体内的总结(五)
- 用unity3d做一个物体围绕另外一个物体旋转。
- Unity脚本,平滑跟随目标物体移动和旋转
- 【Unity】获得当前脚本的物体的transform和gameobject
- unity如何在一个场景中使用另外一个参加烘培好的物体
- 遗留物检测中的物体遗留和移除检测
- 射线检测,单击鼠标是否单击到一个物体上
- 线程通信
- C语言实现二叉树的基本操作
- asar打包与解压指令
- Android端的Socket通信TCP协议Demo
- 三维曲面特征拼接 三维特征拼接 三维扫描特征拼接
- Unity拖拽物体到另外一个物体中的检测相关脚本(萝卜和坑)
- lsscsi
- 视频教程:Java常见面试题目深度解析!
- redis小结
- HiKariCP数据库连接池
- StringUtils.isEmpty()的使用
- PHP内核探索:Apache运行与钩子函数
- [转] 一段双线性插值的代码
- js 单引号 双引号转义