- Home /
Drag to grid script help?
bad engrish incoming
hi everyone
from the serie "the day that i'll finaly decide to start with real android game development those experiments could be certainly useful", this time i'm trying to create a snap-to grid like the one in games like plants vs zombies or bad piggies. So i have to drag objects and then when i release it it just collocate himself into a "slot" of a grid. So my approach was that:
create a grid of prefabs: i use a two dimensional array of Vector3s and for every one of them i instantiate the prefab, wich is just a plane (for debug: at the end it'll just be a collider) with attached a tag called slot (and it just says the prefab's purpose).
As for the drag system, i just use the oldie but goodie physics.raycast system (not so good with little objects but i'll find a way to fix it.
Then, at the event onmousedown, the object's scripts finds the nearest object with the tag slot and the object's position become the nearest slot's position.
Is that a good approach? Anyway, that's the draggable object script:
using UnityEngine;
using System.Collections;
public class draggable : MonoBehaviour
{
//old drag-drop trick
private Ray ray = new Ray();
private RaycastHit hit = new RaycastHit();
//if we're actually touching the object
private bool isTouched = false;
//nearest slot
Transform slot;
//slot tag's name
public string tagName = "Slot";
void OnMouseDown()
{
isTouched = true;
}
void OnMouseUp()
{
isTouched = false;
slot = findNearest();
//if there is a slot
if (slot != null)
{
transform.position = new Vector3(slot.transform.position.x, slot.position.y, 4.9F);
}
}
Transform findNearest()
{
float nearestDistanceSqr = Mathf.Infinity;
Transform taggedGameObjects = GameObject.FindWithTag(tagName).transform;
Transform nearestObj = null;
foreach (GameObject obj in taggedGameObjects)
{
Vector3 objectPos = obj.transform.position;
float distanceSqr = (objectPos - transform.position).sqrMagnitude;
if (distanceSqr < nearestDistanceSqr)
{
nearestObj = obj.transform;
nearestDistanceSqr = distanceSqr;
}
}
return nearestObj;
}
void Update()
{
//drag/drop system
if (isTouched)
{
ray = Camera.main.ScreenPointToRay(Input.mousePosition);
if (Physics.Raycast(ray, out hit))
{
transform.position = new Vector3(hit.point.x, hit.point.y, 4.9F);
}
}
}
}
The problem is that... it doesn't work. Or at least in an half-way, since i can drag the object without problems, but when i release the mouse, the plane doesn't put himself in the nearest slot. Since i can't completely swear about the findNearest's working garancy but i'm pretty sure that i'm missing something.
Could someone help me please?
Many thanks in advance;
regards, asduffo
On a quick read, I did not see why your character is not moving to the nearest slot, but you can likely spot the problem with the debugger. If you have not already tried it, here is a link to get you started:
http://unitygems.com/debugging-game-monodevelop/
If you game is a regular grid like plants vs. zombies, then it is far easier to solve this problem mathematically. If you build your grid on one unit squares, you can position your character by just rounding your X and Z coordinates to the nearest integer. It also makes it easy to calculate the destination of moves.
well i'm not very good with debugs approaches but your link was very useful (it was a little hard anyway since i use visual studio 2012). Anyway, for what i saw, looks like both nearestObj and slot transform are both null for the whole loop. Also before they enter in the findNearest method nearestObj looks like it's not declared even if they're working on it (i know that it could be because it wasn't initialized at the time but i say just for precision)
Answer by robertbu · Jul 15, 2013 at 04:36 PM
You want to use FindGameObjectsWithTag() to find all the tagged objects:
Transform findNearest()
{
float nearestDistanceSqr = Mathf.Infinity;
GameObject[] taggedGameObjects = GameObject.FindGameObjectsWithTag(tagName);
Transform nearestObj = null;
foreach (GameObject obj in taggedGameObjects)
{
Vector3 objectPos = obj.transform.position;
float distanceSqr = (objectPos - transform.position).sqrMagnitude;
if (distanceSqr < nearestDistanceSqr)
{
nearestObj = obj.transform;
nearestDistanceSqr = distanceSqr;
}
}
return nearestObj;
}
Also if you have your game setup on the standard XZ plane, line 28 should be:
transform.position = new Vector3(slot.transform.position.x, 4.9f, slot.position.z);
god may bless you it works!!! I thougt that using an array of gameobjects would be wrong since i were using transforms, but looks like I were wrong. Anyway many many thanks you helped me to finish a thing i were trying to do from a long time :D PS: i use only x-y plane for 2d. Dunno why, maybe because i studied cartesian plane a lot and combined with a year of traditional eclipe-java-opengl es android game development that requires x-y forced for 2d. Anyway thanks