x


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?

more ▼

asked Jan 08 '10 at 01:46 PM

Wizeon gravatar image

Wizeon
52 4 5 11

(comments are locked)
10|3000 characters needed characters left

2 answers: sort voted first

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.

more ▼

answered Jan 08 '10 at 02:25 PM

Ashkan_gc gravatar image

Ashkan_gc
9.1k 33 56 117

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 Might 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.

Jan 10 '10 at 10:06 AM Wizeon

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. :)

Jan 10 '10 at 12:17 PM Ashkan_gc

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.

Jan 10 '10 at 02:05 PM Wizeon

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

Jan 11 '10 at 05:50 AM Ashkan_gc
(comments are locked)
10|3000 characters needed characters left

I've put a grid movement script on the wiki here: http://www.unifycommunity.com/wiki/index.php?title=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.

more ▼

answered Jan 15 '10 at 09:12 AM

Eric5h5 gravatar image

Eric5h5
80.3k 42 132 521

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.

Jan 16 '10 at 09:03 PM Wizeon

I was referring to the other script, which uses GetKey, so gravity isn't an issue.

Jan 16 '10 at 11:33 PM Eric5h5

How can I make a map like you are saying?

May 12 '12 at 03:48 PM BernalCarlos
(comments are locked)
10|3000 characters needed characters left
Your answer
toggle preview:

Up to 2 attachments (including images) can be used with a maximum of 524.3 kB each and 1.0 MB total.

Follow this question

By Email:

Once you sign in you will be able to subscribe for any updates here

By RSS:

Answers

Answers and Comments

Topics:

x5098
x1478
x957

asked: Jan 08 '10 at 01:46 PM

Seen: 9940 times

Last Updated: Oct 31 '12 at 06:40 AM