- Home /
drag drop a object into list objectes
hey all. I wanna drag-drop an object into a list of objects . for example I have a blue object and wanna drag and drop into the white piece. I wrote code like this. but a little bug is in cuz a lot of things should check-in "if" and sometimes my blue object going back to his first position (i think for a lot of conditions and checking a lot of distance, system going to else of foreach ). so... I think need a better solution .if u have any idea help me
foreach (var piece in Piece)
{
if (Vector2.Distance(CurrentColor.transform.position,piece.transform.position)<0.4f && piece.GetComponent<Colorslot>().Entered && !CurrentColor.GetComponent<DragDrop>().dragging )
{
piece.layer = CurrentColor.layer;
piece.GetComponent<Colorslot>().ColorInPosition = true;
CurrentColor.transform.position = piece.transform.position;
CurrentColor.transform.position=new Vector3(CurrentColor.transform.position.x,CurrentColor.transform.position.y,CurrentColor.transform.position.z-10f);
CurrentColor.GetComponent<DragDrop>().draglock = true;
NextColor.transform.position = Vector2.Lerp(NextColorPos.transform.position,CurrentColorPos.transform.position, 0.3F*Time.fixedDeltaTime);
CurrentColor = NextColor;
CurrentColor.GetComponent<DragDrop>().draglock = false;
nextcolor = false;
playerturn = false;
}else if ( !CurrentColor.GetComponent<DragDrop>().dragging && !piece.GetComponent<Colorslot>().Entered)
CurrentColor.transform.position =
Vector2.Lerp(CurrentColor.transform.position, CurrentColorPos.transform.position, 3f);
}
your question is way too vague for us to even understand what's going on.
I wanna drop an object into white places. problem is sometimes when I try to drop into those , it back to the first position and doesn't transform to the white position. ID$$anonymous$$ exactly but cuz a lot condition is in if in foreach and cant calculate fast .some place has a problem. if I drop into another it will work. also if I check with the next color it doesn't work. I made a place with instantiating and added to a list . I also used foreach for checking distance of dragged object.
Answer by metalted · Mar 15, 2020 at 01:27 PM
I've created this little example script to give you an idea how to tackle the problem. The way you are doing it now, by checking distance for every tile in loops is very memory heavy. Running these heavy loops is not useful for when you only really need one of the tiles in the grid. This is more used for when you want to change a lot or even all the tiles. Like a ColorReset() for your tiles for instance. So as to only single out a couple objects that we actually interact with, we can use a raycast to see what we are pointing at and figure it out from there.
using UnityEngine;
public class ObjectGrid : MonoBehaviour
{
public GameObject dragObject;
public Vector3 dragStartPosition;
public int previousLayer;
private void TryDrag()
{
RaycastHit hit;
Ray ray = Camera.main.ScreenPointToRay(Input.mousePosition);
if (Physics.Raycast(ray, out hit))
{
if(hit.collider.tag == "Drag")
{
dragObject = hit.collider.gameObject;
dragStartPosition = hit.point;
previousLayer = dragObject.layer;
dragObject.layer = LayerMask.NameToLayer("Ignore Raycast");
}
}
}
private void Place()
{
RaycastHit hit;
Ray ray = Camera.main.ScreenPointToRay(Input.mousePosition);
if (Physics.Raycast(ray, out hit))
{
bool canPlace = hit.collider.tag == "Place";
dragObject.transform.position = canPlace ? hit.point : dragStartPosition;
dragObject.layer = previousLayer;
dragObject = null;
}
}
void Update()
{
if (Input.GetMouseButton(0))
{
TryDrag();
}
if (Input.GetMouseButtonUp(0))
{
if(dragObject != null)
{
Place();
}
}
if (dragObject != null)
{
RaycastHit hit;
Ray ray = Camera.main.ScreenPointToRay(Input.mousePosition);
if (Physics.Raycast(ray, out hit))
{
Vector3 mousePosition = hit.point;
mousePosition.y = dragStartPosition.y;
dragObject.transform.position = mousePosition;
}
}
}
}
You can use this script right away if you have a top down camera, a plane as a background, and 2 objects, one with tag "Place" and one with tag "Drag". Place the script on an object in the scene. When the mouse button is pressed, a raycast will check if the mouse position is on top of an object with tag "Drag". If it is, move that object with the mouse as long as the button is pressed. Also move it to another layer so that the raycast won't hit it while we are holding it. When the button is released, send out a ray again, but now to check if there is a "Place" tagged object. If there is, place that object on the hit.point, else place it back from where you pick it up.
I like your idea. but have something I can't understand and something is wrong. problems: I wanna if object didn't drop to tiles, back to first position but it don't work (dragObject.transform.position = canPlace ? hit.point : dragStartPosition; ) I think it cuz this code also I didn't understand that question in code. second tiles`s tag and layer wouldn't change.
I define collider for all objects and tiles. i put a debug.log into here
` if(hit.collider.tag == "Drag")
{Debug.Log("ok");
dragObject = hit.collider.gameObject;
dragStartPosition = hit.point;
previousLayer = dragObject.layer;
dragObject.layer = Layer$$anonymous$$ask.NameToLayer("Ignore Raycast");
}`
but it didnt work .what is problem ?
Alright i see. The question mark in the code is part of the ternary operator. It's shorthand for a simple if else statement (and of course much more, but thats not important right now). It is possible to directly convert the ternary operator into an if else:
if (Physics.Raycast(ray, out hit))
{
//When we raycast towards the mouse position, do we detect a collider with tag "Place" ?
bool canPlace = hit.collider.tag == "Place";
//If canPlace is TRUE, so when a "Place" tag is detected, then the new position of the dragged object is the hit position of the raycast. If canPlace is FALSE, then the position of the dragged object is the position that it started from.
dragObject.transform.position = canPlace ? hit.point : dragStartPosition;
//Set the layer of the dragged object back to the layer it was on before we picked it up.
dragObject.layer = previousLayer;
//We are not dragging an object anymore, so set it to null.
dragObject = null;
}
//The equivalent if else version:
if (Physics.Raycast(ray, out hit))
{
if(hit.collider.tag == "Place")
{
dragObject.transform.position = hit.point;
}
else
{
dragObject.transform.position = dragStartPosition;
}
dragObject.layer = previousLayer;
dragObject = null;
}
Also, about your second problem. The tag isn't supposed to change, only the layer does. So if the code you provided doesn't work, it is probably because the object you are trying to drag with the mouse doesn't have the tag "Drag". It doesn't matter what the tag is, as long as the tag you set on the object and the tag you use in code are the same. Because in case your tag is NOT "Drag", the code in the if(hit.collider.tag == "Drag"){} block just won't run.
ty a lot bro for your help. I edit a little your code, I understood when I use spirit 2d,hi.collider.tag doesn't work so I test for a cube and it work. I delete try drag and only with my drag-drop script in my object and onmouseup solved that. changing place method help alot . thanks again