Wayback Machinekoobas.hobune.stream
May JUN Jul
Previous capture 13 Next capture
2021 2022 2023
1 capture
13 Jun 22 - 13 Jun 22
sparklines
Close Help
  • Products
  • Solutions
  • Made with Unity
  • Learning
  • Support & Services
  • Community
  • Asset Store
  • Get Unity

UNITY ACCOUNT

You need a Unity Account to shop in the Online and Asset Stores, participate in the Unity Community and manage your license portfolio. Login Create account
  • Blog
  • Forums
  • Answers
  • Evangelists
  • User Groups
  • Beta Program
  • Advisory Panel

Navigation

  • Home
  • Products
  • Solutions
  • Made with Unity
  • Learning
  • Support & Services
  • Community
    • Blog
    • Forums
    • Answers
    • Evangelists
    • User Groups
    • Beta Program
    • Advisory Panel

Unity account

You need a Unity Account to shop in the Online and Asset Stores, participate in the Unity Community and manage your license portfolio. Login Create account

Language

  • Chinese
  • Spanish
  • Japanese
  • Korean
  • Portuguese
  • Ask a question
  • Spaces
    • Default
    • Help Room
    • META
    • Moderators
    • Topics
    • Questions
    • Users
    • Badges
  • Home /
avatar image
2
Question by Ozale · Mar 13, 2011 at 12:53 AM · gridmultidimarray

Building a multidimensional array for grid movement.

G'day guys.

Some time ago I built the first working prototype of my first 3D game project, a maze game with movement similar to Pacman. It works as desired, but I'd like to improve code efficiency. Currently, there are 4 movement functions (one for each direction, it's necessary for the system I've created), each moving the player exactly '1' unit in the desired direction.

Herein lies the problem: I have an IF statement for each of the 70+ 'positions', each setting which bearings (north, east, south and west) are true. Again, I'm using the direction booleans for other mechanisms such as AI, so I'd like to keep it.

Each 'position' has an IF statement like this:
if (transform.position.z == 0 && transform.position.x == 0){
    north = true; 
    south = false; 
    east = true; 
    west = false; 
    junction = true;
}

I'd like to replace this with a multidimensional array, perhaps that holds one of the 8 possible combinations of available directions for each grid. I know it could also be possible to simply have the movement script detect if the next 'grid' is an available direction.

The only problem is I can't seem to get the array working. I've tried numerous times, but can't seem to get it functioning.

I'm trying to incorporate it into my movement script, an example of which is:

if (actualBearing == 'North' && north == true) {
        moving = true;
        startPosition = transform.position;
        endPosition = transform.position + Vector3.forward * stepDistance * 1;
        stepStartTime = Time.time;
        pivot() ;
    }

I apologise that I've posted on a similar topic before, but after trying many different approaches, I'm still unable to find a way to integrate an array system into my working code. Something along the lines of this would be good:

var grid = new int[
    [1,1,1,1,1,1,1,1,1,1],
    [1,1,1,1,1,1,1,1,1,1],
    [1,1,1,1,1,1,1,1,1,1],
    [1,1,1,1,1,1,1,1,1,1],
    [1,1,1,1,1,1,1,1,1,1],
]

Coupled with an action in each of the four movement directions that 'moves' a grid counter to mirror the player's movement in the scene would be magnificent, but so far my attempts yield no tangible success.

Any advice would be greatly appreciated,

Cheers, - Stew

EDIT! : I have got an array version working, but encountering an error when I try to enable the available directions. My array looks like this:

private var grid = [ ['1','1','1','1','1','0','1','1','1','1'], ['1','0','0','0','1','1','1','0','0','1'], ['1','1','1','0','0','1','0','0','1','1'], ['1','0','1','1','1','1','1','1','1','0'], ['1','0','0','0','1','0','1','0','1','0'], ['1','1','1','1','1','0','1','1','1','1'], ['0','0','1','0','1','1','1','0','0','1'], ['1','1','1','1','1','0','1','1','0','1'], ['1','0','0','1','0','0','0','1','0','1'], ['1','1','1','1','1','1','1','1','1','1'] ];

private var rowIndex = 0; private var colIndex = 0;

This works for movement - I use code like (grid[rowIndex+1][colIndex]) == '1') to check the player can move. But I now need to - before that - make sure the directions are only available when the neighboring 'grid' is available ( == '1' ). I've been experimenting with the below code, but it keeps returning the error 'array index is out of range'.

function checkNorthSouth () {
    if ((grid[rowIndex+1][colIndex]) == '1'){
        north = true;
    }
    else if ((grid[rowIndex-1][colIndex]) == '1'){
        south = true;
    }
}

Anybody know why? (see below)

EDIT (FINAL) : I've got my script to where I need it to be. I changed the array to use INT instead of strings, and to resolve the issue of the index being 'out of range', I simply created a 'border tile' around the map - an extra two rows and two columns, each '0' value. It's a simple fix, but practical. I'll now be moving on to build an 'enemy' AI script.

I'd like to thank everybody who took the time to read, understand or even post on this question. Seeing how you guys work to resolve an issue led me to search for solutions of my own, and as a result I'm growing considerably more comfortable with Javascripting in Unity.

Cheers guys!

Comment
Add comment · Show 3
10 |3000 characters needed characters left characters exceeded
▼
  • Viewable by all users
  • Viewable by moderators
  • Viewable by moderators and the original poster
  • Advanced visibility
Viewable by all users
avatar image Peter G · Mar 13, 2011 at 01:40 AM 1
Share

You should consider using an enum for your bearing. It will save you from checking each direction

avatar image Statement · Mar 13, 2011 at 02:08 PM 0
Share

Yes, and you should consider using FlagsAttribute and store each direction in precomputed array. This way you can just do a simple bit test to see if you can go that direction.

avatar image Statement · Mar 13, 2011 at 03:45 PM 0
Share

(Resurrected comment from deleted answer:) Here's the problem - in the play preview in Unity, it lags a bit. When I build and play, it's fine. - Well, for one, you're storing strings in the array and perfor$$anonymous$$g string tests. It's a bit redundant if you're storing numeric values anyhow. Change your code to use integers ins$$anonymous$$d and you should see some improvement. You can also try change your array from jagged to rectangular since a jagged array creates a level of indirection (Jagged arrays may have variable length sub-arrays).

2 Replies

· Add your reply
  • Sort: 
avatar image
3
Best Answer

Answer by Statement · Mar 13, 2011 at 02:35 PM

I decided to write an example of how you can make use of an edge array. The script doesn't do anything other than building the edges (for faster lookups runtime). I also changed the grid type from string array to int array since it only contained 0 or 1 anyways. To see if you can walk from one position to another, you can just call

if (Test(x, y, Edges.North))
{
    // Ok, we can walk north from x, y.
}

Below is full source:

private var width = 10; private var height = 10;

private var grid = [ [1,1,1,1,1,0,1,1,1,1], [1,0,0,0,1,1,1,0,0,1], [1,1,1,0,0,1,0,0,1,1], [1,0,1,1,1,1,1,1,1,0], [1,0,0,0,1,0,1,0,1,0], [1,1,1,1,1,0,1,1,1,1], [0,0,1,0,1,1,1,0,0,1], [1,1,1,1,1,0,1,1,0,1], [1,0,0,1,0,0,0,1,0,1], [1,1,1,1,1,1,1,1,1,1] ];

private var edges : Edges[,];

@System.Flags enum Edges { None = 0, East = 1, North = 2, West = 4, South = 8, // Edit: added Edges.All as shortcut for East|North|West|South All = 15 };

// Let's build the edges so we don't need to do a lot of checking. BuildEdges();

function BuildEdges() { edges = new Edges[width, height];

 for (var y = 0; y < height; ++y)
 {
     for (var x = 0; x < width; ++x)
     {                
         edges[x, y] = FindEdges(x, y);       
     }
 }

}

function FindEdges(x : int, y : int) : Edges { var edge = Edges.None;

 if (Grid(x, y - 1) == 1)
     edge |= Edges.North;
 if (Grid(x - 1, y) == 1)
     edge |= Edges.West;
 if (Grid(x + 1, y) == 1)
     edge |= Edges.East;
 if (Grid(x, y + 1) == 1)
     edge |= Edges.South;

 return edge;

}

function Grid(x : int, y : int) : int { if (x < 0 || x >= width) return 0; if (y < 0 || y >= height) return 0; return grid[x][y]; }

// Use Test as such: // if (Test(x, y, Edges.West)) // MoveWest();

function Test(x : int, y : int, direction : Edges) : boolean { if (x < 0 || x >= width) return false; if (y < 0 || y >= height) return false;

 return (edges[x, y] &amp; direction) == direction;

}

Comment
Add comment · Show 7 · Share
10 |3000 characters needed characters left characters exceeded
▼
  • Viewable by all users
  • Viewable by moderators
  • Viewable by moderators and the original poster
  • Advanced visibility
Viewable by all users
avatar image dissidently · Mar 13, 2011 at 02:55 PM 1
Share

WOW!!!!! Impressive effort. Someday I'm going to take the time to read all of this. Another time I'm going to need find the time to absorb and understand what this does. For now, Just WOW!

avatar image Statement · Mar 13, 2011 at 03:07 PM 0
Share

Well dissidently, I can see if I can make you help understand it more. The grid (jagged) array represents the level in terms of movement. 1 means you can walk on a point, and 0 means you can't. You can get query this to check if a point is accessible or not with grid[x][y] == 1. Then, for performance reasons, I pre-calculate all the connections for all the grid points so you don't have to test neighbors realtime. That is, I amortize the runtime cost to a slightly heavier start up cost. I use the edges[,] rectangular array for this. (jagged or rectangular really doesn't matter much)

avatar image Statement · Mar 13, 2011 at 03:11 PM 0
Share

edges is similar to grid, but it describes the directions you can take from a point. I used an enum which stores each direction in a bit (thats why they are 1, 2, 4 ,8). This means I can store a value such as BOTH west and north in one value. I find out the cases by checking if the neighboring grid points are 1 and merge them together and finally store the combined value in the right location in edges. Then it's done. We've pre-calculated all possible directions for every point. When we want to check if we can go north from 4, 1, we can see if edges[4, 1] contains north by bitmasking it.

avatar image Statement · Mar 13, 2011 at 03:13 PM 0
Share

You can even check multiple directions at once, say, you want to be able to make a super attack only if you stand at a junction where all neighboring directions are walkable. Then you can try it with Test(x, y, Edges.East | Edges.North | Edges.West | Edges.South). It returns true only if the point has connections to all of those directions.

avatar image Statement · Mar 13, 2011 at 03:18 PM 0
Share

Also, to handle edge cases I chose to block walking outside of the map by returning 0 in the Grid function if the point is out of range. I do similar tests in Test function, although it might seem a bit odd since you're testing a point you can consider "being on". Also, thanks for the discussion, I see a slight index error in my code I'll fix right away.

Show more comments
avatar image
2

Answer by Ashkan_gc · Mar 13, 2011 at 02:51 PM

so the remaining problem is about out of range exception. if rowIndex is 0 and you tell it to read rowIndex-1 then it would try to read rowIndex of -1 which not exist so you should check for 0 and arrayLength -1 before doing the if statement. array.GetLength is the method that you can get the length of a special dimention with it.

Comment
Add comment · Show 1 · Share
10 |3000 characters needed characters left characters exceeded
▼
  • Viewable by all users
  • Viewable by moderators
  • Viewable by moderators and the original poster
  • Advanced visibility
Viewable by all users
avatar image Statement · Mar 13, 2011 at 03:31 PM 0
Share

Actually, it's a jagged array so I doubt you will be able to use GetLength, unless you do arr.GetLength(0) and arr[y].GetLength(0), in which case you can do arr.Length and arr[y].Length just as well. Would it been a rectangular array it would worked like a charm! +1

Your answer

Hint: You can notify a user about this post by typing @username

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

Answers Answers and Comments

2 People are following this question.

avatar image avatar image

Related Questions

How to declare and initialize multidimensional arrays JS? 4 Answers

2D grid for building 1 Answer

Project an hex grid on a non flat terrain. 2 Answers

[Long Post] Constant linear movement in a 2d array grid with auto-turning on detecting a wall 1 Answer

Paint Grid Texture 1 Answer


Enterprise
Social Q&A

Social
Subscribe on YouTube social-youtube Follow on LinkedIn social-linkedin Follow on Twitter social-twitter Follow on Facebook social-facebook Follow on Instagram social-instagram

Footer

  • Purchase
    • Products
    • Subscription
    • Asset Store
    • Unity Gear
    • Resellers
  • Education
    • Students
    • Educators
    • Certification
    • Learn
    • Center of Excellence
  • Download
    • Unity
    • Beta Program
  • Unity Labs
    • Labs
    • Publications
  • Resources
    • Learn platform
    • Community
    • Documentation
    • Unity QA
    • FAQ
    • Services Status
    • Connect
  • About Unity
    • About Us
    • Blog
    • Events
    • Careers
    • Contact
    • Press
    • Partners
    • Affiliates
    • Security
Copyright © 2020 Unity Technologies
  • Legal
  • Privacy Policy
  • Cookies
  • Do Not Sell My Personal Information
  • Cookies Settings
"Unity", Unity logos, and other Unity trademarks are trademarks or registered trademarks of Unity Technologies or its affiliates in the U.S. and elsewhere (more info here). Other names or brands are trademarks of their respective owners.
  • Anonymous
  • Sign in
  • Create
  • Ask a question
  • Spaces
  • Default
  • Help Room
  • META
  • Moderators
  • Explore
  • Topics
  • Questions
  • Users
  • Badges