Moving a cube, one space at a time.

Hi all,

I would like to know how to move a simple cube like a pawn in chess- one space at a time by dragging. I want the player to only drag the cube on the X axis, but limit how far they can drag it. Any thoughts?

Thanks,

Greg

Heya, I just happened to find this:

http://forum.unity3d.com/viewtopic.php?t=3655&highlight=forcemode+velocitychange

Maybe it helps?
AC

Hey thanks, it looks interesting! I'll browse through and see if it helps. Thanks for the tip!

-Greg

What i would use if i were you.

  • Put a plane and a collider (box collider with one scale component to 0.001 to look like a plane) in the plane where the objects move.
  • Put an array of EGOs with the possible positions over that plane.
  • Throw a ray from the camera from the mouse position and collide it with the plane when mouse down.
  • Store the closest EGO in the array.
  • Check if there is a Box in that position of the array.
  • If there is a Box, mark that Box as the moving box
  • Check the distance to the closest EGO in the array while the mouse move.
  • Move the position of the marked Box to the closest EGO detected.
  • Stop the process when mouse up.

This will move the Box in the array while the mouse is dragging to any position in the array. So, the box can move in any direction, any distance and over another Box too, so, you must implement the constrains to move the box to only valid positions by your own since I don’t know the rules of your game.

Omar Rojo

[quote]
-What are EOGs and how do I implement them?

-What do you mean 'throw a ray' from the camera?
[/quote]

Farina asked me this questions on a private message, i post it here so everyone can read and learn.

EGO is for Empty Game Object, so it just mark a position in space (really a transform.. scale, translation and rotation), is a model without rendering components, you can use Models also so you can see where they are, and after they are placed disable the MeshRenderer component so you can avoid the impact on rendering performance, i usually use cubes to mark positions.

A Ray is a line that have an origin, a direction and a length. If you check the Camera.ScreenPointToRay () function in the documentation you can see that you can create a ray from the mouse input position in the direction of the far away plane of the camera at an infinite length. This way you can calculate collisions with the objects the player points with the mouse.

Edit: There is an example at the Input.mousePosition () function in the documentation

Omar Rojo

Thanks again, Omar!

It’s a little over my head, but I think I understand what you’re saying. Any good examples of this that you know of? It’s always much easier to see the code and reverse engineer, as I am a complete novice.

Thank you for your help!

-Greg

(You might want to resize that pic in your first post, because I have to do some pretty heavy horizontal scrolling to read these posts...no 30" monitor here.... ;) )

It depends on what you're doing, but I'd be more inclined just to use an internal data array instead of making empty game objects and raycasting and so on. Javascript doesn't have native multi-dimensional arrays, but you can simulate them easily enough using arrays of arrays. Probably easiest just to make a function for that:

function Array2D (rows : int, columns : int) {
    var array = new Object[rows];
    for (i = 0; i < array.length; i++) {array[i] = new int[columns];}
    return array;
}

Of course, if you want to use something other than integers in the array, then do "array[ i ] = new float" or whatever. Then you make a 2D array by calling it like so:

var gameBoard : Object[] = Array2D(20, 20);

And that will set up a 20x20 array. You then read and store data in the array thus:

if (gameBoard[2][3] == 1) {
    gameBoard[5][7] += 2;
}

That will look at the cell in the array at row 3, column 4 (remember the numbering starts at 0), and if it contains 1, then increase the value of the cell at row 6, column 8 by 2.

(Side note: you can use Javascript arrays instead of built-in arrays, which allows you to resize arrays and other stuff, but you normally have to initialize the values in this case. For example, the code above would generate an error, unless the cell at 5,7 was specifically set to 0 or some other number first. Plus Javascript arrays are also slower, but I think that would hardly make a difference unless you're making heavy use of arrays every frame.)

This way you can store the state of the game board in the array, and use it for AI, as well as for moving pieces in 3D. If all you care about is movement, then you don't need to bother with arrays. Just use a mouse drag script and use transform.position.x to modify the x position only, plus Mathf.Clamp to limit the distance. But it looks like you're doing some sort of board game thing. If so, I could give you a simplistic example using the above techniques, if you're still having trouble.

--Eric

Hi Eric,

Do you think you could provide an example of the above mentioned arrays? I'm a little confused, especially about how to actually construct an array in the game environment itself.

Thanks,

Greg

Of course you need an array to store the actual state of the board, as i said, i don't know about the game's rules so i didn't went there.

The proposal of the plane and the array of EGOs if for the easy drag and drop objects over the board on a 3D interface. I have implemented it to create a 3D windows system where the user can have some windows floating around showing information and he can put them everywhere on the screen with the mouse, I did this to avoid using the GUI interface that Unity provides since i found it too poor.

When you understand that theory, you will know that it's easy and very powerful way to implement drag and drop 3D elements on a 3D environment.

Unfortunately, i can't show you that code or application since it's property of my employer, and actually it have a lot of other stuff mixed, for other kind of tasks, that you probably will not understand easy and/or care about.

Edit: I don't know any tutorial about it, i came with the idea myself so probably there is a better method to do it, but mine works fine..

Omar Rojo

Hi Omar,

Would you happen to have any examples of such an array that I could inspect and play around with?

Thanks,

Greg

I can’t work on that here at the job, sorry, because it’s a long implementation task.

You can check this classes in the documentation though.

  • Input (Input.mousePosition)
  • Screen (Screen.ScreenPointToRay)
  • MonoBehaviour (MonoBehaviour.OnMouseDrag, .OnMouseDown, .OnMouseUp)

That's cool, I'll do my best to understand with this information. Thanks again!

-Greg

Omar’s technique would be excellent if you want to set up objects in the editor with drag/drop. If you’re just doing basic stuff from code, here’s a simplistic and incomplete example script:

var boardX : int = 0;
var boardZ : int = 0;
var sensitivity : float = 30;
private var objectX : float;
private var objectZ : float;
private var gameBoard : Object[];

function Start () {
	gameBoard = Array2D(20, 20);
	objectX = boardX;
	objectZ = boardZ;
	transform.position = Vector3(objectX, 0, objectZ);
}

function OnMouseDrag () {
	var maxMoveLeft = 1;
	if (boardX == 0) {maxMoveLeft = 0;}
	else if (gameBoard[boardX-1][boardZ] != 0) {maxMoveLeft = 0;}
	
	var maxMoveRight = 1;
	if (boardX == 19) {maxMoveRight = 0;}
	else if (gameBoard[boardX+1][boardZ] != 0) {maxMoveRight = 0;}
	
	var currentPos = transform.position.x + Input.GetAxis("Mouse X") * sensitivity * Time.deltaTime;
	transform.position.x = Mathf.Clamp(currentPos, objectX-maxMoveLeft, objectX+maxMoveRight);
}

function Array2D (rows : int, columns : int) {
	var array = new Object[rows];
	for (i = 0; i < array.length; i++) {array[i] = new int[columns];}
	return array;
}

If you attach that script to an object, you can drag it left or right one “space”. It’s set up so that 1 cell in the array corresponds to 1 unit in the game world, but that can of course be changed to anything.

boardX and boardZ are variables that represent the current location in the array. objectX and objectZ are variables that represent the actual location of the object in 3D space on its x and z axes. So first you initialize the array, and set the object’s x and z coordinates from the x and z location in the array. The default of 0 for board X and boardZ therefore means the object gets set to (0, 0, 0) in 3D space. Changing boardX and boardZ in the inspector will cause the object to be moved to the appropriate location when you run the game. We use the objectX/Z variables later for movement in 3D space.

For the mouse dragging function, we use two variables to limit how far the object can be moved…maxMoveLeft and maxMoveRight. We start off by assuming that you can move one unit to the left. Then check to see if the current position in the array is at the left edge (0), and if so, set maxMoveLeft to 0 so the player won’t be able to move left. Also check to see if the space to the left of the object’s position in the array holds anything. There won’t be anything blocking the object in this example aside from the left edge, but that allows for the possibility when you implement other pieces.

(You could simplify the logic here by filling in the edge rows and columns of the array with some value to begin with. That way you wouldn’t have to check for out-of-bounds, since the object would never be able to move into the edge rows/columns in the first place.)

Then do the same thing for the right…first assume you can move, check for right edge, check space to right.

Then we get the current position from the object’s x location in 3D space. Add to that input from mouse movement on the horizontal axis, multiplied by whatever sensitivity is set to, and make sure it’s framerate independent by using Time.deltaTime. Then we clamp that value by subtracting/adding the maxMoveLeft/Right variables to the starting position.

So if you run that with the default location of 0 for boardX, you won’t be able to drag left because we’re at the left edge of the array. If you change boardX to, say, 5 then you can drag left and right. If you change it to 19, then you can’t drag right.

Note that this example is hard-coded to use a 20x20 array. That’s probably a Bad Thing™, unless you’re really really sure you want a particular size and won’t ever change your mind. It would be better to set variables for the array size and check against those. But I wrote this fast. :wink:

This is just to get you started…you can’t do anything other than drag left or right one space. You’d probably want to implement an OnMouseUp function that has logic for what to do when the player lets up on the button. You’d update boardX, at least, to represent the new location in the array (just add or subtract 1, depending on whether the object was dragged left or right), and then update objectX correspondingly. You’d also likely want to implement dragging forward and backward, which is just the same thing except you’d use boardZ and objectZ and check the vertical axis.

You’d also have to decide how to handle the dragging exactly…what if the player just drags the object a little ways? You can have it “snap” to the nearest space on the board. Or you could have the object automatically slide into the next space. Also, the dragging here is implemented in a really basic way…there’s a topic around here somewhere about having the object actually follow the mouse pointer, which is a little more complicated but certainly possible.

–Eric

Wow, I don’t know what to say, Eric, that is so cool of you! I think I’m getting the idea of how the script should be used, but still lacking the know how. Do I need to create the gameboard as a game object somehow?
I a little confused about how to construct the array as well.
I applied the script to one of my cubes and it disappeared at run time. It must have been missing something important that I did not include.

I suppose I should really get a hold of a java scripting book for beginners, perhaps that would be useful.

Again, you are very kind to help me,

thanks!

Greg

I think Farina that you are lacking of knowledge and should start with something simpler? I didn’t read what eric said in the last post but it’s a lot and you still have questions…

Don’t get it the wrong way… but something simpler is a good way to start.

What about moving the boxes with the keyboard? Activate one and then move it along the array positions? Or even simpler, move a box in space by the keyboard first by a given unit in the World space without having a board to constraint it.

Everyone should start looking at the simplest so the complex become obvious.

Omar Rojo

Yes, I think you are correct. I think I need to learn much more before I try and tackle something like this. You have been quite a help, thank you!

Make a new scene with nothing in it, and put a default cube at location 0,0,0, and have a camera looking at the cube. Then put that script on the cube and run the game. That way you can at least see what's going on...you don't need a game board or anything at this point.

But yeah, it might be better to back up and come back to this later. The complex stuff is actually just a bunch of simple stuff all connected together. So when you understand the basics, you see ways to accomplish what you want. (Although sometimes it can take a long time, with much effort and bug-hunting along the way...nobody ever claimed programming was trivial. ;) )

--Eric

Oh great, it works! I think I will spend some time with this and try to understand it a little more before I get too ambitious. Thanks again, Eric, you have been an enormous help!

-Greg

Look Farina what i did for you, is what i mean, i keep it as simple as possible, i should have done some other stuff but for you to understand it.

Any questions post it but im going home now and i don't think i will be entering the forum for the weekend.

Eric check it too so you can see what i mean :smile:

But i mean it.. start simple or you will always see a wall in front of the complex

Omar Rojo

36203--1331--$draggablepieces_321.unitypackage (46.1 KB)

Oh, I know what you meant. :wink: It just seemed a little much to start out with in this case.

–Eric