using UnityEngine;
public class DragAndSwap : MonoBehaviour
{
private Camera cam;
private GameObject selectedObject;
private GameObject collidedObject;
private Vector3 offset;
private Vector3 originalPosition;
private Vector3 collidedOriginalPosition; // Store the original position of the collided object
void Start()
{
cam = Camera.main;
}
void Update()
{
if (Input.GetMouseButtonDown(0)) // Left mouse button click
{
Ray ray = cam.ScreenPointToRay(Input.mousePosition);
RaycastHit hit;
if (Physics.Raycast(ray, out hit)) // Check if we hit an object
{
selectedObject = hit.collider.gameObject;
originalPosition = selectedObject.transform.position; // Save original position
Vector3 screenPoint = cam.WorldToScreenPoint(selectedObject.transform.position);
offset = selectedObject.transform.position - cam.ScreenToWorldPoint(new Vector3(Input.mousePosition.x, Input.mousePosition.y, screenPoint.z));
}
}
if (Input.GetMouseButton(0) && selectedObject) // While dragging
{
Vector3 screenPoint = new Vector3(Input.mousePosition.x, Input.mousePosition.y, cam.WorldToScreenPoint(selectedObject.transform.position).z);
Vector3 newWorldPosition = cam.ScreenToWorldPoint(screenPoint) + offset;
selectedObject.transform.position = new Vector3(newWorldPosition.x, newWorldPosition.y, originalPosition.z); // Keep Z position fixed
}
if (Input.GetMouseButtonUp(0) && selectedObject) // When released
{
if (collidedObject != null && collidedObject.CompareTag("Draggable"))
{
// Swap positions
Vector3 tempPosition = collidedObject.transform.position;
collidedObject.transform.position = originalPosition; // Move collided object to the original position of the selected object
selectedObject.transform.position = tempPosition; // Move selected object to the collided object's position
}
else
{
// No collision -> Move back to original position
selectedObject.transform.position = originalPosition;
}
selectedObject = null;
collidedObject = null; // Reset the collided object after swap or reset
}
}
void OnTriggerEnter(Collider other)
{
if (selectedObject != null && other.gameObject.CompareTag("Draggable"))
{
collidedObject = other.gameObject; // Store reference to the object we collided with
collidedOriginalPosition = collidedObject.transform.position; // Store the original position of the collided object
}
}
void OnTriggerExit(Collider other)
{
if (collidedObject == other.gameObject)
{
collidedObject = null; // Reset if the selected object moves away
}
}
}
我希望所选对象进行交换并进入其正确的位置,但另一个对象正在进入正确的位置。与其他对象交换后所选对象在移动到其原始位置时不会移动到交换位置。请帮助我在此代码中做错了什么?
我试图逐步解决它。我可能会认为问题可能是在selectedObject OginalPosition中未正确存储,而另一个Raeson可能是触发功能是不正确的调用吗?要获得当前情况的概述,例如,播放器(用户)在一个场景上的对象A和对象B可以选择其中一个(任何一个要特定的),因为两个对象都将附有单obehaviour脚本给他们。在情况下,单击对象A(设置了选定的变量),并且在单击时也确定偏移量,以使其远离屏幕(也许在表面或某物上)。现在,由于所选对象设置了以下代码可以运行:
if (Input.GetMouseButton(0) && selectedObject) // While dragging
{
Vector3 screenPoint = new Vector3(Input.mousePosition.x, Input.mousePosition.y, cam.WorldToScreenPoint(selectedObject.transform.position).z);
Vector3 newWorldPosition = cam.ScreenToWorldPoint(screenPoint) + offset;
selectedObject.transform.position = new Vector3(newWorldPosition.x, newWorldPosition.y, originalPosition.z); // Keep Z position fixed
}
现在,对象A的位置A(已更新选定的对象,直到未释放鼠标按钮为止)。 对象B(相撞对象)是通过使用标签检查设置的(不建议使用,但可以工作)。当扳机退出时,将对象B(相撞对象)设置为null,即对象A不再具有对其的引用。 在鼠标按钮上释放了对象A和对象B的位置。如果碰撞对象为null,则对象A(选定的对象)移至其原始位置。现在,据我了解,当触发器退出时,您将对象B(相撞对象)设置为空。这些物体应完全交换,除非和直到它们相互碰撞,否则碰撞结束并远离扳机边界,它们不会交换。
void OnTriggerExit(Collider other) {
if (collidedObject == other.gameObject) {
collidedObject = null; // Reset if the selected object moves away
}
}
删除此代码块将使代码按预期工作,但是如果您打算将对象与任何最新的相撞对象交换,那将很容易出错,而不是删除它可能是最简单的解决方案。
提示使代码更好:
利用接口的使用示例“ iDragable”使代码可重复使用。