在 2 个游戏对象之间拖放
Drag and Drop between 2 gameObjects
我的场景中有 2 个球体。我希望能够将我的鼠标从一个球体拖放到另一个球体,并在拖动时有一个指示器(例如一条直线)。释放鼠标按钮后,我想在第一个球体中存储另一个球体(作为 GameObject)。
我在UnityScript中需要这个,但我可以接受C#的想法。
到目前为止,我已经考虑过第一个 Sphere 上的 onMouseDown
事件,然后 onMouseEnter
到另一个 sphere,我会将数据存储在一些全局变量中(我不知道如何做)并且在 onMouseExit
的情况下,我将把全局变量设为 null。
然后 onMouseUp
在第一个球体上,我会将全局变量存储在按下的对象(球体)中。
关于如何操作的任何提示和技巧?
Assumptions/Setup
您正在 2D 世界空间中工作;这部分解决方案的拖动对象逻辑需要更改。
点击拖动后设置父级,指的是将未点击的对象设置为点击的父级的子级。
相机应该是正交相机;使用透视相机会导致拖动与您认为应该的位置不对齐。
为了使拖动工作,我创建了一个用作 'background' 到 2D 场景的四边形,并将其放在一个名为 'background' 的新图层上.然后设置layermask字段只使用背景层。
为线条渲染器创建并设置一个 material,(我在上面的示例中使用 Particles/Additive 着色器), 以及我使用 Start Width: 0.75
, End Width: 0
的线条渲染器的参数,并确保勾选 Use World Space
。
说明
首先将 otherSphere
字段设置为指向场景中的另一个球体。 OnMouseDown
和 OnMouseUp
切换 mouseDown 布尔值,用于确定是否应更新线渲染器。这些也用于转动 on/off 线渲染器和 set/remove 两个球体的父变换。
为了获得要拖动到的位置,我使用方法 ScreenPointToRay 根据鼠标在屏幕上的位置获得一条射线。如果你想为这个拖动功能添加平滑,你应该在底部启用 if (...) else
语句,并将 lerpTime 设置为一个值(0.25 对我来说效果很好)。
注意;当您释放鼠标时,父对象会立即设置,因此两个对象最终都会被拖动,但是子对象 将 return 无论如何都会回到原来的位置。
[RequireComponent(typeof(LineRenderer))]
public class ConnectedSphere : MonoBehaviour
{
[SerializeField]
private Transform m_otherSphere;
[SerializeField]
private float m_lerpTime;
[SerializeField]
private LayerMask m_layerMask;
private LineRenderer m_lineRenderer;
private bool m_mouseDown;
private Vector3 m_position;
private RaycastHit m_hit;
public void Start()
{
m_lineRenderer = GetComponent<LineRenderer>();
m_lineRenderer.enabled = false;
m_position = transform.position;
}
public void OnMouseDown()
{
//Un-parent objects
transform.parent = null;
m_otherSphere.parent = null;
m_mouseDown = true;
m_lineRenderer.enabled = true;
}
public void OnMouseUp()
{
//Parent other object
m_otherSphere.parent = transform;
m_mouseDown = false;
m_lineRenderer.enabled = false;
}
public void Update()
{
//Update line renderer and target position whilst mouse down
if (m_mouseDown)
{
//Set line renderer
m_lineRenderer.SetPosition(0, transform.position);
m_lineRenderer.SetPosition(1, m_otherSphere.position);
//Get mouse world position
if (Physics.Raycast(Camera.main.ScreenPointToRay(Input.mousePosition), out m_hit, m_layerMask))
{
m_position.x = m_hit.point.x;
m_position.y = m_hit.point.y;
}
}
//Set position (2D world space)
//if (m_lerpTime == 0f)
transform.position = m_position;
//else
//transform.position = Vector3.Lerp(transform.position, m_position, Time.deltaTime / m_lerpTime);
}
}
希望这对某人有所帮助。
我的场景中有 2 个球体。我希望能够将我的鼠标从一个球体拖放到另一个球体,并在拖动时有一个指示器(例如一条直线)。释放鼠标按钮后,我想在第一个球体中存储另一个球体(作为 GameObject)。
我在UnityScript中需要这个,但我可以接受C#的想法。
到目前为止,我已经考虑过第一个 Sphere 上的 onMouseDown
事件,然后 onMouseEnter
到另一个 sphere,我会将数据存储在一些全局变量中(我不知道如何做)并且在 onMouseExit
的情况下,我将把全局变量设为 null。
然后 onMouseUp
在第一个球体上,我会将全局变量存储在按下的对象(球体)中。
关于如何操作的任何提示和技巧?
Assumptions/Setup
您正在 2D 世界空间中工作;这部分解决方案的拖动对象逻辑需要更改。
点击拖动后设置父级,指的是将未点击的对象设置为点击的父级的子级。
相机应该是正交相机;使用透视相机会导致拖动与您认为应该的位置不对齐。
为了使拖动工作,我创建了一个用作 'background' 到 2D 场景的四边形,并将其放在一个名为 'background' 的新图层上.然后设置layermask字段只使用背景层。
为线条渲染器创建并设置一个 material,(我在上面的示例中使用 Particles/Additive 着色器), 以及我使用
Start Width: 0.75
,End Width: 0
的线条渲染器的参数,并确保勾选Use World Space
。
说明
首先将 otherSphere
字段设置为指向场景中的另一个球体。 OnMouseDown
和 OnMouseUp
切换 mouseDown 布尔值,用于确定是否应更新线渲染器。这些也用于转动 on/off 线渲染器和 set/remove 两个球体的父变换。
为了获得要拖动到的位置,我使用方法 ScreenPointToRay 根据鼠标在屏幕上的位置获得一条射线。如果你想为这个拖动功能添加平滑,你应该在底部启用 if (...) else
语句,并将 lerpTime 设置为一个值(0.25 对我来说效果很好)。
注意;当您释放鼠标时,父对象会立即设置,因此两个对象最终都会被拖动,但是子对象 将 return 无论如何都会回到原来的位置。
[RequireComponent(typeof(LineRenderer))]
public class ConnectedSphere : MonoBehaviour
{
[SerializeField]
private Transform m_otherSphere;
[SerializeField]
private float m_lerpTime;
[SerializeField]
private LayerMask m_layerMask;
private LineRenderer m_lineRenderer;
private bool m_mouseDown;
private Vector3 m_position;
private RaycastHit m_hit;
public void Start()
{
m_lineRenderer = GetComponent<LineRenderer>();
m_lineRenderer.enabled = false;
m_position = transform.position;
}
public void OnMouseDown()
{
//Un-parent objects
transform.parent = null;
m_otherSphere.parent = null;
m_mouseDown = true;
m_lineRenderer.enabled = true;
}
public void OnMouseUp()
{
//Parent other object
m_otherSphere.parent = transform;
m_mouseDown = false;
m_lineRenderer.enabled = false;
}
public void Update()
{
//Update line renderer and target position whilst mouse down
if (m_mouseDown)
{
//Set line renderer
m_lineRenderer.SetPosition(0, transform.position);
m_lineRenderer.SetPosition(1, m_otherSphere.position);
//Get mouse world position
if (Physics.Raycast(Camera.main.ScreenPointToRay(Input.mousePosition), out m_hit, m_layerMask))
{
m_position.x = m_hit.point.x;
m_position.y = m_hit.point.y;
}
}
//Set position (2D world space)
//if (m_lerpTime == 0f)
transform.position = m_position;
//else
//transform.position = Vector3.Lerp(transform.position, m_position, Time.deltaTime / m_lerpTime);
}
}
希望这对某人有所帮助。