- Home /
Basic movement in a grid
This must be very basic thing to do but I can't figure it out. I'm trying to move things in a grid layout when user uses movement keys. I've got everything else figured out but I can't figure out how to actually move the thing. How can I animate the movement of 1 unit to about 0.5 seconds? If I use transform.position it move there, yes, but in one frame. It should also block moving it again before the new position has been reached so move commands won't stack up 60 times a second.
Another thing. This is a rpg style game, like the pokemon on handhelds. Should I use tiles for the maps or what? If I use tiles the hierarchy is full of them (think 300 x 300 map, so 9000 tiles) and I suspect it'll lag the game. How should I construct the terrain?
Answer by Ashkan_gc · Jan 08, 2010 at 02:25 PM
i made a script that can help you. i never used it in my project but i think you can use it now basicaly in these situations you should use coroutines. if you want to move something 16 meter in a second you should add 16*time.deltaTime to it each frame.
using UnityEngine;
using System.Collections;
public class move : MonoBehaviour
{
bool canmove = true; //indicate if a keyboard key can move a piece Vector3 targetPosition; //temporary value for moving (used in coroutines) public int speed = 10; public int gridSize=1;
void Update() { if (Input.GetKey(KeyCode.UpArrow) == true && canmove == true) { canmove = false; StartCoroutine (MoveInGrid((int)transform.position.x, (int)transform.position.y+gridSize, (int)transform.position.z)); } if (Input.GetKey(KeyCode.RightArrow) == true && canmove == true) { canmove = false; StartCoroutine(MoveInGrid((int)transform.position.x+gridSize, (int)transform.position.y, (int)transform.position.z)); } if (Input.GetKey(KeyCode.LeftArrow) == true && canmove == true) { canmove = false; StartCoroutine(MoveInGrid((int)transform.position.x-gridSize, (int)transform.position.y, (int)transform.position.z)); } if (Input.GetKey(KeyCode.DownArrow) == true && canmove == true) { canmove = false; StartCoroutine(MoveInGrid((int)transform.position.x, (int)transform.position.y-gridSize, (int)transform.position.z)); } }
IEnumerator MoveInGrid(int x,int y,int z) { while (transform.position.x != x || transform.position.y != y || transform.position.z != z) { //moving x forward if (transform.position.x < x) { //moving the point by speed targetPosition.x = speed Time.deltaTime; //check if the point goes more than it should go and if yes clamp it back if (targetPosition.x + transform.position.x > x) { targetPosition.x = x - transform.position.x; } } //moving x backward else if (transform.position.x > x) { //moving the point by speed targetPosition.x = -speed Time.deltaTime; //check if the point goes more than it should go and if yes clamp it back if (targetPosition.x + transform.position.x < x) { targetPosition.x = -(transform.position.x - x); } } else //x is unchanged so should be 0 in translate function { targetPosition.x = 0; } //moving y forward if (transform.position.y < y) { //moving the point by speed targetPosition.y = speed Time.deltaTime; //check if the point goes more than it should go and if yes clamp it back if (targetPosition.y + transform.position.y > y) { targetPosition.y = y - transform.position.y; } } //moving y backward else if (transform.position.y > y) { //moving the point by speed targetPosition.y = -speed Time.deltaTime; //check if the point goes more than it should go and if yes clamp it back if (targetPosition.y + transform.position.y < y) { targetPosition.y = -(transform.position.y - y); } } else //y is unchanged so it should be zero { targetPosition.y = 0; } //moving z forward if (transform.position.z < z) { //moving the point by speed targetPosition.z = speed Time.deltaTime; //check if the point goes more than it should go and if yes clamp it back if (targetPosition.z + transform.position.z > z) { targetPosition.z = z - transform.position.z; } } //moving z backward else if (transform.position.z > z) { //moving the point by speed targetPosition.z = -speed Time.deltaTime; //check if the point goes more than it should go and if yes clamp it back if (targetPosition.z + transform.position.z < z) { targetPosition.z = -(transform.position.z - z); } } else //z is unchanged so should be zero in translate function { targetPosition.z = 0; } transform.Translate(targetPosition); yield return 0; } //the work is ended now congratulation canmove = true; }
} the important function is MoveInGrid that takes values as target position in world space and move the gameobject to there. see my Update function to learn it's usage. i used local positions in my Update function. the script's gridsize is equal in x,y,z and you can set this size and speed inside inspector. the component is completely reusable but you can modify it or only use MoveInGrid coroutine.
This works pretty well. I'm just getting some stuttering movement, made a post in the forums, http://forum.unity3d.com/viewtopic.php?p=253253#253253 $$anonymous$$ight be caused by this or something else. Now the only question left was the best way to create the terrain but I think I can handle it without advice. Though it can be answered, won't kill you for helping me.
does it kill you if you vote this question up? :) just kidding i don't know what is the best approach but use as less textures as possible. is your game 2D? what properties a tile should have? does it contain code? i think you should create another question for that and vote good answers up to admire who answered you. :)
I tried to vote it up but it requires 15 rep, and that I don't have, yet. Sorry :(
But to the terrain, basically the game is 2D but it's rendered in 3D, think pokemon diamond and pearl (the whole game will be a clone). It will be plain squares, so currently I'm using just basic planes. I haven't noticed a noticeable performance hit. I'm using 11mb vram (is the vram capped to 32mb in the indie version) and have just a basic house, a cube as player and 2 other small models on the scene. Plus 1500 terrain tiles. I don't know if changing textures on some will hit performance, will test it.
you should go in this way for all of your active objects. use planes with textures for them. you can use plane colliders too. but for textures that they don't have code, you can have a big terrain and paint them on the terrain. i think there is no performance difference but i did not test it. doing the whole game with planes can help you to create level editors for users and is a good approach
Answer by Eric5h5 · Jan 15, 2010 at 09:12 AM
I've put a grid movement script on the wiki here: http://wiki.unity3d.com/index.php/GridMove
I'm afraid the other script has some issues, such as being wayyyy too long ;), repeating the same transform.position twice on "grid lines" (leading to slight but visible hiccups when traversing more than one square in a row), and sometimes moving two squares at once.
As far as the maps go, they should be done using a single plane, where each square is an individually UV mapped tile, using a texture atlas. Using separate objects for each tile is a recipe for massively worse performance.
I don't have a problem with the object moving more than one square in a row. It's likely to be caused because of the "gravity" of your input isn't high. GetAxisRaw gets rid of this easily.
I was referring to the other script, which uses Get$$anonymous$$ey, so gravity isn't an issue.
thanks a lot for the Grid$$anonymous$$ove script, you are awesome. One question though. How could I make this compatible with colliders? Right now the script seems to be disabling the colliding component as the walls of my scene can't containt the player anymore