Transforming several objects via OnGUI in Unity

edited in Questions and Answers
Howzit dudes, so I finally got cracking with Unity and need some advice. I am trying to replicate the puzzle game Cryptica I've been playing on my Android where you have to match cubes with their corresponding patterns on a puzzle board. In Cryptica all cubes move simultaneously and their relative positions can only be altered when hitting the end of the board or when blocked by static cubes.

Here is my [Updated] code:

var cubeMovement = 11;
var greenCube;

function Start() {
	 greenCube = GameObject.Find("Green");
}

function Update () {

}

function OnGUI () {
    //Move dynamic cubes
    if (GUI.Button (Rect (250,150,50,50), "Up")) {
    	moveUp();
    }
	
	if (GUI.Button (Rect (350,250,50,50), "Right")) {
		moveRight();
	}
	
	if (GUI.Button (Rect (250,350,50,50), "Down")) {
		moveDown();
	}
	
	if (GUI.Button (Rect (150,250,50,50), "Left")) {
		moveLeft();
	}
}

function moveUp() {
	transform.Translate(cubeMovement,0,0);
	greenCube.transform.Translate(cubeMovement,0,0);
}

function moveRight() {
	transform.Translate(0,0,-cubeMovement);
	greenCube.transform.Translate(0,0,-cubeMovement);
}

function moveDown() {
	transform.Translate(-cubeMovement,0,0);
	greenCube.transform.Translate(-cubeMovement,0,0);
}

function moveLeft() {
	transform.Translate(0,0,cubeMovement);
	greenCube.transform.Translate(0,0,cubeMovement);
}


If I attach the script to each cube then OnGUI will only move one cube at a time. How do I transform several objects simultaneously? Is there a better way to approach this?

Shot!
Screen Shot 2012-07-09 at 3.48.22 PM.png
742 x 330 - 71K

Comments

  • edited
    I believe that that will be because of the fact that you will be drawing the same GUI multiple times, and only the "top" or "foremost" GUI layer is being drawn. One object should have the OnGUI, and then you call a procedure for the movement on each object (I can look up what Im suggesting if you dont know what I mean, just cant find my Unity projects atm :P)

    Also, I put your code into code tags.
    [code]code here[/code ]

    (minus the space in the right brace)
  • Yeah, @edg3 is right: The way you're explaining it there, every cube has its own GUI and only one of them (probably the last one to be created or added to the scene, although maybe it's depth dependent) is actually having its GUI displayed and interacted with, which is why only that cube moves.

    Try building a controller object that maintains a list of all the cubes and moves each of them as necessary. The controller would be the only object with any GUI calls :)
  • Thanks guys! Had to go through some of the scripting reference to get your suggestion right but it's working now. Have updated the code in the first post to reflect.
  • Ah, I see that you're still doing this in your "red" cube object. I really think it would be a better idea to handle movement and player interaction via a completely different script object (that doesn't have any meshes associated with it at all) that handles movement. That way you can move more than just two cubes by search for all your cubes, or have each cube register itself with the controller. That would make life much easier...
  • Thanks Dis, yes, you're right but I don't yet understand how to implement that. Just stoked that I'm actually getting something to do what I want it to do :D
  • Found my stuff this morning, its the GameObject's "BroadcastMessage" to call functions in objects.

    /// Calls the function ApplyDamage with a value of 5
    gameObject.BroadcastMessage ("ApplyDamage", 5.0);
    
    // Every script attached to the game object and all its children
    // that has a ApplyDamage function will be called.
    function ApplyDamage (damage : float) {
        print (damage);
    }

    You can have a list of GameObjects that you go through and call the procedure from the control object with. (So the control object has a list of GameObject and the OnGUI)

    So the invisible control object would have a script something like this (C#-like pseudocode):
    public List<GameObject> objects;
    
    void OnGUI () {
        //Move dynamic cubes
            if (GUI.Button (Rect (250,150,50,50), "Up")) {
                  foreach (var go in objects)
                  {
        	          go.BroadcastMessage("move",0);
                  }
            }
    	
    	if (GUI.Button (Rect (350,250,50,50), "Right")) {
                  foreach (var go in objects)
                  {
        	          go.BroadcastMessage("move",1);
                  }
    	}
    	
    	if (GUI.Button (Rect (250,350,50,50), "Down")) {
                  foreach (var go in objects)
                  {
        	          go.BroadcastMessage("move",2);
                  }
    	}
    	
    	if (GUI.Button (Rect (150,250,50,50), "Left")) {
                  foreach (var go in objects)
                  {
        	          go.BroadcastMessage("move",3);
                  }
    	}
    }


    And the script in the cubes would be something like:
    void moveUp(int direction) {
            switch (direction)
            {
    	case 0: { //up
                transform.Translate(cubeMovement,0,0);
    	    greenCube.transform.Translate(cubeMovement,0,0);
                       } break;
            case 1: { //right
    	    //todo: right code
                       } break;
            case 2: { //down
    	    //todo: down code
                       } break;
            case 3: { //left
    	    //todo left code
                       } break;
            }
    }


    I hope that makes more sense? The control object will be separate and just call the function on the game objects that require the movement.
  • I will have to dissect this as I'm not a coder and it seems a lot to take in 0_o but I think I'm getting the just of it. Preciate it!
Sign In or Register to comment.