【Unity基础】Unity 2D实现拖拽功能的10种方法

方法1. 基于 Update 循环的拖拽方法 (DragDrop2D)
代码概述
using System.Collections;
using System.Collections.Generic;
using UnityEngine;public class DragDrop2D : MonoBehaviour
{bool isDraggable;bool isDragging;Collider2D objectCollider;void Start(){objectCollider = GetComponent<Collider2D>();isDraggable = false;isDragging = false;}void Update(){DragAndDrop();}void DragAndDrop(){Vector2 mousePosition = Camera.main.ScreenToWorldPoint(Input.mousePosition);if (Input.GetMouseButtonDown(0)){if (objectCollider == Physics2D.OverlapPoint(mousePosition)){isDraggable = true;}else{isDraggable = false;}if (isDraggable){isDragging = true;}}if (isDragging){this.transform.position = mousePosition;}if (Input.GetMouseButtonUp(0)){isDraggable = false;isDragging = false;}}
}
特点与分析
- 实现方式:
- 手动输入检测:在
Update方法中通过检测鼠标按下、拖动和松开事件来实现拖拽。 - 碰撞检测:使用
Physics2D.OverlapPoint手动判断鼠标是否点击在对象的碰撞器上。
- 手动输入检测:在
- 优点:
- 简单直观:适合初学者理解和实现基础的拖拽功能。
- 缺点:
- 代码复杂度:需要手动管理多个状态变量(
isDraggable和isDragging)。 - 用户体验:直接将对象的位置设置为鼠标位置,可能导致拖拽时对象“跳跃”到鼠标位置,尤其是点击点不是对象中心时。
- 可维护性:随着功能需求的增加,代码扩展性较差,难以处理复杂的交互情况。
- 代码复杂度:需要手动管理多个状态变量(
方法2. 基于内置鼠标事件的方法 (`DragDropByMouse)
代码概述
using System.Collections;
using System.Collections.Generic;
using UnityEngine;public class DragDropByMouse : MonoBehaviour
{private bool isDragging;public void OnMouseDown(){isDragging = true;}public void OnMouseUp(){isDragging = false;}public void OnMouseDrag(){Vector2 mousePosition = Camera.main.ScreenToWorldPoint(Input.mousePosition) - transform.position;transform.Translate(mousePosition);}private void OnTriggerEnter2D(Collider2D other){Debug.Log("collision " + other.name);}
}
特点与分析
- 实现方式:
- 使用Unity内置事件方法:依赖
OnMouseDown、OnMouseUp和OnMouseDrag等内置事件方法处理拖拽逻辑。 - 自动交互检测:Unity自动调用这些事件方法,当鼠标与对象的碰撞器交互时,无需手动检测。
- 使用Unity内置事件方法:依赖
- 优点:
- 代码简洁:通过内置事件方法管理拖拽状态,代码更简洁易懂。
- 自动处理交互:无需手动检测鼠标与对象的碰撞,简化了交互逻辑。
- 额外功能:实现了
OnTriggerEnter2D方法,可以在拖拽过程中检测与其他碰撞器的碰撞,增加了互动功能。
- 缺点:
- 拖拽体验:
OnMouseDrag方法中使用transform.Translate基于位移更新位置,但计算方式可能不如其他方法平滑,尤其是在高帧率或快速移动时。 - 灵活性有限:依赖于Unity的内置事件系统,对于更复杂的拖拽需求可能需要额外的实现。
- 拖拽体验:
方法3. 基于事件接口 (EventSystem) 的拖拽方法 (`DragDropWithEvent)
代码概述
using UnityEngine;
using UnityEngine.EventSystems;public class DragDropWithEvent : MonoBehaviour, IBeginDragHandler, IDragHandler, IEndDragHandler
{private Vector3 offset; // 偏移量,用来保持拖动时鼠标和物体之间的相对位置private Camera mainCamera; // 主摄像机,用于屏幕坐标到世界坐标的转换private void Awake(){mainCamera = Camera.main;}public void OnBeginDrag(PointerEventData eventData){Vector3 mousePos = mainCamera.ScreenToWorldPoint(eventData.position);offset = transform.position - new Vector3(mousePos.x, mousePos.y, transform.position.z);Debug.Log("Begin drag");}public void OnDrag(PointerEventData eventData){Vector3 mousePos = mainCamera.ScreenToWorldPoint(eventData.position);transform.position = new Vector3(mousePos.x, mousePos.y, transform.position.z) + offset;Debug.Log("On Dragging");}public void OnEndDrag(PointerEventData eventData){Debug.Log("End Drag");}
}
特点与分析
- 实现方式:
- 使用
EventSystem接口:实现IBeginDragHandler、IDragHandler和IEndDragHandler接口,通过这些接口方法处理拖拽逻辑。 - 偏移量管理:计算并保持拖拽时鼠标与对象之间的相对偏移量,确保拖拽过程中的平滑和自然。
- 使用
- 优点:
- 拖拽体验流畅:通过计算偏移量,避免了拖拽时对象位置的“跳跃”,提供更自然的拖拽体验。
- 利用
EventSystem:更好地集成到Unity的事件系统中,支持更复杂的交互需求。 - 扩展性强:可以轻松添加更多的拖拽相关逻辑,如拖拽过程中触发的其他事件或效果。
- 缺点:
- 依赖
EventSystem:需要确保场景中存在EventSystem,否则事件接口可能无法正常工作。 - 稍复杂的实现:相较于基于内置鼠标事件的方法,实现接口需要更多的代码和理解。
- 依赖
三种方法的对比总结
| 特性/方法 | 基于 Update 循环 (DragDrop2D) | 基于内置鼠标事件 (`DragDropByMouse) | 基于 EventSystem 接口 (`DragDropWithEvent) |
|---|---|---|---|
| 实现方式 | 手动检测鼠标输入和碰撞 | 使用Unity内置的鼠标事件方法 | 实现 EventSystem 的拖拽接口 |
| 代码复杂度 | 中等,需管理多个状态变量 | 低,依赖内置事件方法 | 中等,需实现接口并管理偏移量 |
| 拖拽体验 | 可能出现位置跳跃 | 平滑性一般,基于位移更新 | 非常流畅,保持鼠标与对象的相对位置 |
| 自动交互检测 | 手动检测 | 自动检测 | 自动检测 |
| 扩展性 | 较差,难以处理复杂交互 | 一般,较难扩展更多功能 | 优秀,易于添加更多拖拽相关功能 |
| 依赖组件 | 需要 Collider2D | 需要 Collider2D | 需要 EventSystem 和 Collider2D |
| 额外功能 | 无 | 支持碰撞检测 | 可集成更多基于事件的功能 |
| 适用场景 | 简单拖拽需求 | 基础拖拽和碰撞检测需求 | 需要流畅拖拽体验和高度可扩展性的复杂需求 |
推荐选择
- 简单项目或初学者:如果项目需求较为简单,且开发者对Unity的事件系统不太熟悉,基于内置鼠标事件的方法 (
DragDropByMouse) 是一个不错的选择。它实现简单,适合快速上手。 - 需要更流畅体验和扩展性的项目:对于需要更高质量的拖拽体验以及可能扩展更多交互功能的项目,基于
EventSystem接口的方法 (DragDropWithEvent) 更为适合。它提供了更自然的拖拽体验,并且易于集成更多复杂的逻辑。 - 需要自定义拖拽逻辑:如果项目有特定的拖拽需求,且需要完全控制拖拽过程的每个细节,基于
Update循环的方法 (DragDrop2D) 可能更灵活,但同时也需要更多的代码管理和逻辑控制。
除了上述三种方法,Unity中实现2D物体拖拽还有其他多种方法。不同的方法适用于不同的需求和场景。以下是一些常见的替代方法及其详细说明:
方法4. 基于 Rigidbody2D 的物理拖拽
概述
利用 Rigidbody2D 组件,通过物理引擎实现拖拽效果。这种方法适用于需要物理反馈(如碰撞、重力等)的拖拽场景。
实现步骤
-
添加组件
- 为要拖拽的物体添加
Rigidbody2D和Collider2D组件。 - 设置
Rigidbody2D的Body Type为Dynamic,以便受物理引擎控制。
- 为要拖拽的物体添加
-
创建拖拽脚本
using UnityEngine;public class PhysicsDrag2D : MonoBehaviour {private Rigidbody2D rb;private Camera mainCamera;private bool isDragging = false;private Vector3 offset;void Start(){rb = GetComponent<Rigidbody2D>();mainCamera = Camera.main;}void Update(){Vector2 mousePosition = mainCamera.ScreenToWorldPoint(Input.mousePosition);if (Input.GetMouseButtonDown(0)){Collider2D collider = Physics2D.OverlapPoint(mousePosition);if (collider != null && collider.gameObject == this.gameObject){isDragging = true;offset = transform.position - new Vector3(mousePosition.x, mousePosition.y, transform.position.z);}}if (Input.GetMouseButtonUp(0)){isDragging = false;}}void FixedUpdate(){if (isDragging){Vector2 targetPosition = (Vector2)mainCamera.ScreenToWorldPoint(Input.mousePosition) + (Vector2)offset;rb.MovePosition(targetPosition);}} }
特点与分析
- 优点:
- 物理反馈:拖拽过程中物体受物理引擎控制,适用于需要物理交互的场景。
- 平滑移动:利用
Rigidbody2D.MovePosition实现平滑的物体移动。
- 缺点:
- 复杂性增加:需要理解和管理物理组件及其参数。
- 性能开销:对于大量可拖拽物体,物理计算可能带来性能开销。
方法5. 使用 Unity 的新输入系统(Unity Input System)
概述
Unity 的新输入系统提供更灵活和可扩展的输入处理方式。可以结合新输入系统来实现拖拽功能,适用于需要支持多种输入设备(鼠标、触摸、游戏手柄等)的项目。
实现步骤
-
安装新输入系统
- 在 Unity Package Manager 中安装 “Input System” 包。
- 按提示切换到新输入系统,并重启编辑器。
-
创建输入动作
- 创建一个新的
Input Actions资产,配置鼠标或触摸输入动作。
- 创建一个新的
-
编写拖拽脚本
using UnityEngine; using UnityEngine.InputSystem;public class NewInputDrag2D : MonoBehaviour {private Camera mainCamera;private bool isDragging = false;private Vector3 offset;private void Awake(){mainCamera = Camera.main;}public void OnPointerDown(InputAction.CallbackContext context){if (context.performed){Vector2 mousePos = mainCamera.ScreenToWorldPoint(Mouse.current.position.ReadValue());Collider2D collider = Physics2D.OverlapPoint(mousePos);if (collider != null && collider.gameObject == this.gameObject){isDragging = true;offset = transform.position - new Vector3(mousePos.x, mousePos.y, transform.position.z);}}}public void OnPointerUp(InputAction.CallbackContext context){if (context.performed){isDragging = false;}}public void OnDrag(InputAction.CallbackContext context){if (isDragging){Vector2 mousePos = mainCamera.ScreenToWorldPoint(Mouse.current.position.ReadValue());transform.position = new Vector3(mousePos.x, mousePos.y, transform.position.z) + offset;}} } -
绑定输入动作
- 在
Input Actions资产中,将拖拽相关的动作绑定到脚本中的方法,如OnPointerDown、OnPointerUp和OnDrag。
- 在
特点与分析
- 优点:
- 多设备支持:方便支持鼠标、触摸和其他输入设备。
- 可扩展性:通过
Input Actions资产轻松管理和扩展输入。
- 缺点:
- 学习曲线:新输入系统相对复杂,需要一定的学习和配置时间。
- 额外配置:需要额外的输入动作配置和绑定步骤。
方法6. 基于 Raycasting 的拖拽
概述
通过自定义射线检测(Raycasting)来识别并拖拽对象。这种方法适用于需要更精确控制拖拽逻辑的场景。
实现步骤
-
创建拖拽脚本
using UnityEngine;public class RaycastDrag2D : MonoBehaviour {private Camera mainCamera;private bool isDragging = false;private Vector3 offset;private Rigidbody2D rb;void Start(){mainCamera = Camera.main;rb = GetComponent<Rigidbody2D>();}void Update(){Vector2 mousePos = mainCamera.ScreenToWorldPoint(Input.mousePosition);if (Input.GetMouseButtonDown(0)){RaycastHit2D hit = Physics2D.Raycast(mousePos, Vector2.zero);if (hit.collider != null && hit.collider.gameObject == this.gameObject){isDragging = true;offset = transform.position - new Vector3(mousePos.x, mousePos.y, transform.position.z);}}if (Input.GetMouseButtonUp(0)){isDragging = false;}if (isDragging){Vector2 targetPos = mousePos + (Vector2)offset;rb.MovePosition(targetPos);}} }
特点与分析
- 优点:
- 精确控制:可以自定义射线检测的逻辑,适应复杂的交互需求。
- 性能优化:射线检测可以减少不必要的碰撞检测,提高性能,尤其在有大量对象时。
- 缺点:
- 复杂性增加:需要理解射线检测和物理层的交互。
- 配置要求:需要合理设置碰撞器和物理层,避免射线误判。
方法7. 使用 Tweening 库进行动画拖拽
概述
利用 Tweening 库(如 DOTween)通过插值动画实现拖拽效果,适用于需要平滑动画过渡和复杂拖拽效果的场景。
实现步骤
-
安装 Tweening 库
- 以 DOTween 为例,在 Unity Asset Store 或通过 Package Manager 安装 DOTween。
-
创建拖拽脚本
using UnityEngine; using DG.Tweening;public class TweenDrag2D : MonoBehaviour {private Camera mainCamera;private bool isDragging = false;private Vector3 offset;void Start(){mainCamera = Camera.main;}void Update(){Vector2 mousePos = mainCamera.ScreenToWorldPoint(Input.mousePosition);if (Input.GetMouseButtonDown(0)){Collider2D collider = Physics2D.OverlapPoint(mousePos);if (collider != null && collider.gameObject == this.gameObject){isDragging = true;offset = transform.position - new Vector3(mousePos.x, mousePos.y, transform.position.z);}}if (Input.GetMouseButtonUp(0)){isDragging = false;}if (isDragging){Vector3 targetPos = new Vector3(mousePos.x, mousePos.y, transform.position.z) + offset;transform.DOMove(targetPos, 0.1f).SetEase(Ease.Linear);}} }
特点与分析
- 优点:
- 平滑动画:Tweening 库提供平滑的动画过渡,提升用户体验。
- 丰富的动画选项:可以轻松添加缓动效果、延迟等复杂动画。
- 缺点:
- 额外依赖:需要引入第三方库,增加项目依赖。
- 性能开销:大量使用 Tweening 动画可能带来性能开销,需优化使用。
方法8. 使用 UI 元素的拖拽
概述
将2D物体作为 UI 元素(如 Image 或 Button),利用 Unity 的 UI 系统进行拖拽。适用于需要与其他 UI 组件集成的拖拽场景。
实现步骤
-
设置 UI 元素
- 将要拖拽的物体作为 UI 元素添加到
Canvas下,确保有CanvasGroup组件。
- 将要拖拽的物体作为 UI 元素添加到
-
创建拖拽脚本
using UnityEngine; using UnityEngine.EventSystems;public class UIDrag2D : MonoBehaviour, IBeginDragHandler, IDragHandler, IEndDragHandler {private Canvas canvas;private RectTransform rectTransform;private CanvasGroup canvasGroup;private Vector3 offset;void Awake(){rectTransform = GetComponent<RectTransform>();canvasGroup = GetComponent<CanvasGroup>();canvas = GetComponentInParent<Canvas>();}public void OnBeginDrag(PointerEventData eventData){canvasGroup.alpha = 0.6f; // 半透明表示正在拖拽canvasGroup.blocksRaycasts = false;Vector3 globalMousePos;if (RectTransformUtility.ScreenPointToWorldPointInRectangle(rectTransform, eventData.position, eventData.pressEventCamera, out globalMousePos)){offset = rectTransform.position - globalMousePos;}}public void OnDrag(PointerEventData eventData){Vector3 globalMousePos;if (RectTransformUtility.ScreenPointToWorldPointInRectangle(rectTransform, eventData.position, eventData.pressEventCamera, out globalMousePos)){rectTransform.position = globalMousePos + offset;}}public void OnEndDrag(PointerEventData eventData){canvasGroup.alpha = 1f;canvasGroup.blocksRaycasts = true;} }
特点与分析
- 优点:
- 与 UI 集成:易于与其他 UI 组件(如按钮、面板)集成。
- 简化输入管理:利用 UI 系统自动处理输入事件。
- 缺点:
- 限制于 UI 元素:适用于 UI 元素,若需要拖拽非 UI 2D物体,需额外调整。
- 层级管理:需要合理管理 UI 元素的层级和渲染顺序,避免遮挡问题。
方法9. 使用第三方插件
概述
利用 Unity Asset Store 上的第三方插件(如 NaughtyAttributes, EasyTouch, Lean Touch 等)来简化拖拽功能的实现。这些插件通常提供丰富的功能和更高的灵活性。
实现步骤
- 选择并安装插件
- 根据项目需求选择合适的插件,下载安装并导入到项目中。
- 配置插件
- 按照插件的文档和指南进行配置,通常包括添加组件、设置参数等。
- 编写拖拽逻辑
- 利用插件提供的接口和方法,实现自定义的拖拽行为。
特点与分析
- 优点:
- 功能丰富:第三方插件通常提供比内置方法更丰富的功能,如多点触控支持、惯性拖拽等。
- 节省开发时间:利用现成的解决方案,减少自定义代码编写。
- 缺点:
- 依赖性:引入第三方插件增加项目依赖,需关注插件的维护和兼容性。
- 学习成本:需要学习和理解插件的使用方法和接口。
方法10. 基于动画控制器的拖拽
概述
通过动画控制器(Animator)和状态机管理拖拽状态,结合动画过渡实现拖拽效果。这种方法适用于需要复杂状态管理和动画过渡的拖拽场景。
实现步骤
-
创建动画状态
- 在 Animator 中创建拖拽相关的动画状态(如 Idle、Dragging)。
-
配置动画过渡
- 设置状态之间的过渡条件,如布尔参数
isDragging。
- 设置状态之间的过渡条件,如布尔参数
-
编写拖拽脚本
using UnityEngine;public class AnimatorDrag2D : MonoBehaviour {private Animator animator;private Camera mainCamera;private bool isDragging = false;private Vector3 offset;void Start(){animator = GetComponent<Animator>();mainCamera = Camera.main;}void Update(){Vector2 mousePos = mainCamera.ScreenToWorldPoint(Input.mousePosition);if (Input.GetMouseButtonDown(0)){Collider2D collider = Physics2D.OverlapPoint(mousePos);if (collider != null && collider.gameObject == this.gameObject){isDragging = true;animator.SetBool("isDragging", true);offset = transform.position - new Vector3(mousePos.x, mousePos.y, transform.position.z);}}if (Input.GetMouseButtonUp(0)){isDragging = false;animator.SetBool("isDragging", false);}if (isDragging){transform.position = new Vector3(mousePos.x, mousePos.y, transform.position.z) + offset;}} }
特点与分析
- 优点:
- 动画集成:便于与其他动画效果集成,实现更复杂的视觉反馈。
- 状态管理:利用 Animator 的状态机管理拖拽状态,清晰且易于维护。
- 缺点:
- 复杂性高:需要设置 Animator Controller 和动画状态,增加开发复杂度。
- 性能开销:频繁的动画状态切换可能带来性能开销,需优化。
方法11. 使用触摸事件(针对移动设备)
概述
在移动设备上,通过处理触摸事件来实现拖拽。这种方法适用于需要支持触摸交互的2D拖拽场景。
实现步骤
-
编写拖拽脚本
using UnityEngine;public class TouchDrag2D : MonoBehaviour {private Camera mainCamera;private bool isDragging = false;private Vector3 offset;private int touchId = -1;void Start(){mainCamera = Camera.main;}void Update(){foreach (Touch touch in Input.touches){Vector2 touchPos = mainCamera.ScreenToWorldPoint(touch.position);if (touch.phase == TouchPhase.Began){Collider2D collider = Physics2D.OverlapPoint(touchPos);if (collider != null && collider.gameObject == this.gameObject){isDragging = true;touchId = touch.fingerId;offset = transform.position - new Vector3(touchPos.x, touchPos.y, transform.position.z);}}if (touch.fingerId == touchId){if (touch.phase == TouchPhase.Moved || touch.phase == TouchPhase.Stationary){if (isDragging){Vector3 newPos = new Vector3(touchPos.x, touchPos.y, transform.position.z) + offset;transform.position = newPos;}}if (touch.phase == TouchPhase.Ended || touch.phase == TouchPhase.Canceled){isDragging = false;touchId = -1;}}}} }
特点与分析
- 优点:
- 移动优化:专为触摸设备设计,支持多点触控。
- 直观交互:适合触摸屏的直观拖拽操作。
- 缺点:
- 平台限制:主要针对移动设备,桌面设备可能不适用。
- 复杂性增加:需要处理多点触控和不同触摸阶段。
总结与对比
以下是对这些拖拽方法的总结与对比:
| 方法 | 实现方式 | 优点 | 缺点 | 适用场景 |
|---|---|---|---|---|
基于 Update 循环 | 手动检测输入和碰撞 | 简单直观,适合初学者 | 代码复杂,用户体验可能不佳 | 基础拖拽需求,初学者项目 |
| 基于内置鼠标事件 | 使用 OnMouseDown 等事件方法 | 代码简洁,自动处理交互 | 拖拽体验有限,灵活性较差 | 基础拖拽和简单碰撞检测需求 |
基于 EventSystem 接口 | 实现 IBeginDragHandler 等接口 | 流畅拖拽体验,易扩展 | 依赖 EventSystem,稍复杂 | 需要流畅拖拽和复杂交互的项目 |
基于 Rigidbody2D 物理 | 使用物理组件控制位置 | 物理反馈,平滑移动 | 需要管理物理组件,性能开销 | 需要物理交互和反馈的拖拽场景 |
| 使用新输入系统 | 利用 Unity 新输入系统处理输入 | 多设备支持,灵活可扩展 | 学习曲线陡峭,额外配置 | 需要支持多种输入设备的项目 |
| 基于 Raycasting | 自定义射线检测拖拽逻辑 | 精确控制,性能优化 | 实现复杂,需管理射线检测 | 需要精确控制和优化性能的拖拽场景 |
| 使用 Tweening 库 | 利用动画插值实现拖拽 | 平滑动画,丰富动画选项 | 依赖第三方库,性能开销 | 需要复杂动画过渡和视觉效果的拖拽项目 |
| 使用 UI 元素拖拽 | 将物体作为 UI 元素,利用 UI 系统拖拽 | 与 UI 集成,简化输入管理 | 仅适用于 UI 元素,层级管理复杂 | 需要与 UI 组件集成的拖拽场景 |
| 使用第三方插件 | 利用 Asset Store 插件简化实现 | 功能丰富,节省开发时间 | 增加项目依赖,需学习插件使用方法 | 需要快速实现复杂拖拽功能的项目 |
| 基于动画控制器 | 利用 Animator 管理拖拽状态和动画 | 与动画集成,清晰状态管理 | 实现复杂,可能影响性能 | 需要复杂状态管理和动画过渡的拖拽项目 |
| 使用触摸事件 | 处理触摸输入实现拖拽 | 支持多点触控,适合移动设备 | 平台限制,需处理多点触控 | 移动设备上的触摸拖拽场景 |
推荐选择
- 简单项目或初学者:如果项目需求简单,且希望快速实现拖拽功能,基于内置鼠标事件的方法 (
DragDropCard) 或 基于Update循环的方法 (DragDrop2D) 是不错的选择。 - 需要流畅体验和复杂交互:对于需要更流畅拖拽体验和易于扩展的项目,基于
EventSystem接口的方法 (Draggable2DSprite) 更为合适。 - 需要物理反馈:如果拖拽过程中需要物理交互,基于
Rigidbody2D的物理拖拽 是最佳选择。 - 多设备支持:需要支持鼠标、触摸等多种输入设备时,使用 Unity 新输入系统 或 触摸事件方法 更为合适。
- 动画需求:需要丰富的动画效果和状态管理时,使用 Tweening 库 或 基于动画控制器的方法 可以实现更复杂的拖拽效果。
- 集成 UI:如果拖拽对象是 UI 元素,使用 UI 元素的拖拽方法 更为方便。
- 节省开发时间:对于需要快速实现复杂拖拽功能的项目,使用第三方插件 是一个高效的选择。
结论
Unity 提供了多种实现2D物体拖拽的方法,每种方法都有其适用的场景和优缺点。选择合适的方法取决于项目的具体需求、开发者的熟悉程度以及对拖拽体验和功能扩展性的要求。理解各种方法的实现机制和适用场景,有助于在实际开发中做出更合适的选择。
相关文章:
【Unity基础】Unity 2D实现拖拽功能的10种方法
方法1. 基于 Update 循环的拖拽方法 (DragDrop2D) 代码概述 using System.Collections; using System.Collections.Generic; using UnityEngine;public class DragDrop2D : MonoBehaviour {bool isDraggable;bool isDragging;Collider2D objectCollider;void Start(){objectC…...
duxapp中兼容多端的 BoxShadow 阴影组件
由于RN 安卓端对阴影的支持不太完善,使用这个组件可以实现阴影效果 在RN端是使用 react-native-fast-shadow 实现的 示例 import { BoxShadow, Text } from /duxui<BoxShadow><Text>这是内容</Text> </BoxShadow>Props 继承自Taro的View…...
服务器---centos上安装docker并使用docker配置jenkins
要在 Docker 中安装 Jenkins 并进行管理,可以按照以下步骤操作: 1. 安装 Docker 首先,确保你的系统已经安装了 Docker。如果尚未安装,可以使用以下命令进行安装: 在 CentOS 上安装 Docker sudo yum install -y yum-utils sudo yum-config-manager --add-repo https://…...
Linux系统操作03|chmod、vim
上文: Linux系统操作02|基本命令-CSDN博客 目录 六、chmod:给文件设置权限 1、字母法 2、数字法(用的最多) 七、vim:代码编写和文本编辑 1、启动和退出 1️⃣启动 2️⃣退出 2、vim基本操作 六、chmod&#x…...
数据库同步中间件DBSyncer安装配置及使用
1、介绍 DBSyncer(英[dbsɪŋkɜː],美[dbsɪŋkɜː 简称dbs)是一款开源的数据同步中间件,提供MySQL、Oracle、SqlServer、PostgreSQL、Elasticsearch(ES)、Kafka、File、SQL等同步场景。支持上传插件自定义同步转换业务…...
虚幻5描边轮廓材质
很多游戏内都有这种描边效果,挺实用也挺好看的,简单复刻一下 效果演示: Linethickness可以控制轮廓线条的粗细 这样连完,然后放到网格体细节的覆层材质上即可 可以自己更改粗细大小和颜色...
ISP帳戶會記錄什麼資訊?
許多用戶並不知道ISP會記錄有關線上活動的大量資訊。從流覽歷史記錄到數據使用情況,ISP經常收集和保留用戶數據,引發一系列隱私問題。 ISP 記錄哪些數據? ISP可以根據其隱私政策記錄各種類型的資訊。常見的記錄數據包括: 1.流覽…...
Facebook如何避免因IP变动而封号?实用指南
随着Facebook在个人社交与商业推广中的广泛应用,越来越多的用户面临因“IP变动”而被封号的问题。尤其是跨境电商、广告运营者和多账号管理用户,这种情况可能严重影响正常使用和业务发展。那么,如何避免因IP变动导致的封号问题?本…...
EXCEL数据清洗的几个功能总结备忘
目录 0 参考教材 1 用EXCEL进行数据清洗的几个功能 2 删除重复值: 3 找到缺失值等 4 大小写转换 5 类型转化 6 识别空格 0 参考教材 精通EXCEL数据统计与分析,中国,李宗璋用EXCEL学统计学,日EXCEL统计分析与决策&#x…...
web网页连接MQTT,显示数据与下发控制命令
web网页连接MQTT,显示数据与下发控制命令 零、前言 在完成一些设备作品后,常常会因为没有一个上位机用来实时检测数据和下发命令而苦恼,在上一篇文章中提到了怎么白嫖阿里云服务器,并且在上面搭建了属于自己的web网站。那么现在…...
数据结构day3作业
一、完整功能【顺序表】的创建 【seqList.h】 #ifndef __SEQLIST_H__ #define __SEQLIST_H__#include <stdio.h> #include <string.h> #include <stdlib.h>//宏定义,线性表的最大容量 #define MAX 30//类型重定义,表示要存放数据的类…...
Android SDK 平台工具版本说明
Android SDK Platform-Tools 是 Android SDK 的一个组件。它包含与 Android 平台进行交互的工具,主要是 adb 和 fastboot。虽然 adb 是 Android 应用开发所必需的,但应用开发者通常仅使用 Studio 安装的副本。如果您想直接从命令行使用 adb 并且未安装 S…...
Sharding-jdbc基本使用步骤以及执行原理剖析
一、基本使用步骤 1、需求说明 使用sharding-jdbc完成对订单表的水平分表,通过快速入门的开发,了解sharding-jdbc使用方法 人工创建两张表,t_order_1和t_order_2,这两张表是订单表拆分后的表,通过sharding-jdbc向订…...
mysql重置root密码(适用于5.7和8.0)
今天出一期重置mysql root密码的教程,适用于5.7和8.0,在网上搜索了很多的教程发现都没有效果,浪费了很多时间,尝试了多次之后发现这种方式是最稳妥的,那么废话不多说,往下看: 目录 第一步&…...
Linux下SVN客户端保存账号密码
参考文章:解决:Linux上SVN 1.12版本以上无法直接存储明文密码_linux svn 保存密码-CSDN博客新版本svn使用gpg-agent存储密码-CSDN博客svn之无法让 SVN 存储密码,即使配置设置为允许_编程设计_ITGUEST 方法一:明文方式保存密码 首…...
centos7.9 gcc升级到11.2.1
一、信息查看 # cat /etc/redhat-release CentOS Linux release 7.9.2009 (Core) # gcc --version gcc (GCC) 4.8.5 20150623 (Red Hat 4.8.5-44) Copyright © 2015 Free Software Foundation, Inc. 本程序是自由软件;请参看源代码的版权声明。本软件没有任…...
HQChart使用教程30-K线图如何对接第3方数据42-DRAWTEXTREL,DRAWTEXTABS数据结构
HQChart使用教程30-K线图如何对接第3方数据42-DRAWTEXTREL,DRAWTEXTABS数据结构 效果图DRAWTEXTREL示例数据结构说明nametypecolorDrawVAlignDrawAlignDrawDrawTypeDrawDataFont DRAWTEXTABS示例数据结构说明nametypecolorDrawVAlignDrawAlignDrawDrawTypeDrawDataFont 效果图 …...
数仓高频面试 | 数仓为什么要分层
大家好,我是大D呀。 关于数仓分层,在面试过程中几乎是必问的。不过,面试官一般也不会直接考你数仓为什么要分层,而是在你介绍项目时,可能会换一种形式来穿插着问,比如数据链路为什么要这样设计,…...
网络安全—部署CA证书服务器
网络拓扑 两台服务器在同一网段即可,即能够互相ping通。 安装步骤 安装证书系统 首先我们对计算机名进行确认,安装了证书系统后我们是不能随意更改计算机名字的,因为以后颁发的证书都是和计算机也就是这一台的服务器名字有关。 修改完成后开…...
MATLAB中circshift函数的原理分析——psf2otf函数的核心
之所以讲到MATLAB中circshift函数,也是源于Rafael Gonzalez的这个图,作为前几篇答廖老师问的blog的基础。 Rafael Gonzalez的这个图无论从哪幅图到哪幅图都不是直接的傅里叶变换或傅里叶逆变换,需要循环移位,即circshift函数。 这…...
golang循环变量捕获问题
在 Go 语言中,当在循环中启动协程(goroutine)时,如果在协程闭包中直接引用循环变量,可能会遇到一个常见的陷阱 - 循环变量捕获问题。让我详细解释一下: 问题背景 看这个代码片段: fo…...
Linux简单的操作
ls ls 查看当前目录 ll 查看详细内容 ls -a 查看所有的内容 ls --help 查看方法文档 pwd pwd 查看当前路径 cd cd 转路径 cd .. 转上一级路径 cd 名 转换路径 …...
2021-03-15 iview一些问题
1.iview 在使用tree组件时,发现没有set类的方法,只有get,那么要改变tree值,只能遍历treeData,递归修改treeData的checked,发现无法更改,原因在于check模式下,子元素的勾选状态跟父节…...
Android 之 kotlin 语言学习笔记三(Kotlin-Java 互操作)
参考官方文档:https://developer.android.google.cn/kotlin/interop?hlzh-cn 一、Java(供 Kotlin 使用) 1、不得使用硬关键字 不要使用 Kotlin 的任何硬关键字作为方法的名称 或字段。允许使用 Kotlin 的软关键字、修饰符关键字和特殊标识…...
sipsak:SIP瑞士军刀!全参数详细教程!Kali Linux教程!
简介 sipsak 是一个面向会话初始协议 (SIP) 应用程序开发人员和管理员的小型命令行工具。它可以用于对 SIP 应用程序和设备进行一些简单的测试。 sipsak 是一款 SIP 压力和诊断实用程序。它通过 sip-uri 向服务器发送 SIP 请求,并检查收到的响应。它以以下模式之一…...
动态 Web 开发技术入门篇
一、HTTP 协议核心 1.1 HTTP 基础 协议全称 :HyperText Transfer Protocol(超文本传输协议) 默认端口 :HTTP 使用 80 端口,HTTPS 使用 443 端口。 请求方法 : GET :用于获取资源,…...
uniapp手机号一键登录保姆级教程(包含前端和后端)
目录 前置条件创建uniapp项目并关联uniClound云空间开启一键登录模块并开通一键登录服务编写云函数并上传部署获取手机号流程(第一种) 前端直接调用云函数获取手机号(第三种)后台调用云函数获取手机号 错误码常见问题 前置条件 手机安装有sim卡手机开启…...
HTML前端开发:JavaScript 获取元素方法详解
作为前端开发者,高效获取 DOM 元素是必备技能。以下是 JS 中核心的获取元素方法,分为两大系列: 一、getElementBy... 系列 传统方法,直接通过 DOM 接口访问,返回动态集合(元素变化会实时更新)。…...
Kubernetes 节点自动伸缩(Cluster Autoscaler)原理与实践
在 Kubernetes 集群中,如何在保障应用高可用的同时有效地管理资源,一直是运维人员和开发者关注的重点。随着微服务架构的普及,集群内各个服务的负载波动日趋明显,传统的手动扩缩容方式已无法满足实时性和弹性需求。 Cluster Auto…...
【WebSocket】SpringBoot项目中使用WebSocket
1. 导入坐标 如果springboot父工程没有加入websocket的起步依赖,添加它的坐标的时候需要带上版本号。 <dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-websocket</artifactId> </dep…...
