selecting object in game

Hi,

Sorry if I this question has already been posted, I looked but did not find any thread relative.

So what I need to do is selecting an object (or clone / instance of object) just by clicking on it with mouse - let’s say with kind of “highlighting” on it and being able to move / rotate it or whatever change by clicking NOT on it but on GUI element or using keys. Then I must be able to :

  • select another object
    or
  • unselect all

Guess I should manage the second part of the script (transform actions) but I have no idea about selecting / unselecting the object itself / highlighting while it’s selected and “recording” the fact it’s selected so that when I use gui buttons or keys this object rotates or moves, etc.

Any help please.

i would have one selection manager which keeps track of the selected object(s) (for example keeps a reference of it). and when you do operations it applies these to the object. and when you select another one the reference is changed.
selection can be done with the mouseover event.

for highlighting there is a package for purchase here: Buy Plugins & Code from CodeCanyon
but you can use simpler aproaches like drawing a frame around it or simply alter material color.

thanx,
Yes I think altering material color will do the stuff. For selection I rather thought about mousedown than mouseover but nevermind, guess code structure would be the same anyway.
The point is the “reference”. What variable / code element should be used to get / record this ? Unfortunately this is way over my code knowledge. I’m okay for writing and attaching “direct” scripts on objects or creating links between two of them (for example a button that will make an object move or material change) but have no idea about this switching selection stuff.

Any more about this selection manager / referencing tip ?

simply use the transform for the gameobject itself, or if everything relevant is handeled in a certain component (script) retrieve it with getcomponent and store this. you are completely free. but if you need to access different components (like material + script) the first aproach is probably the better.

what you describe in your example is basically a selection. simply store a reference to the “selected” object, do some special drawing/highlighting, and route all user actions (movement, commands) to it. and additionally handle the change of selections properly (like deselect) or make advanced selections (rectangle select, additive select).

have colliders on all of your scene objects, then you can use OnMouseEnter() OnMouseOver() and OnMouseExit() functions, and so you can select your objects. (you can use onmouseenter to change it’s renderer.material.color to another value, and onmouseexit to change it back to the previous value, and inside onmouseover you can check for clicks and store that object in a var in the GUI control script)

The thing with the GUI (since GUI is over all your scene objects will be easy to do) is that in onmouseover if you clicked that obj you will store it as a refference inside the GUI control script, so you will be able to make simple buttons, for example

if(GUI.Button(new Rect(_x, _y, x, y), "rotate_left")){
	reference.transform.eulerAngles += new Vector3(0, 1, 0);
}

Place this script on each object you want to be able to select. (and make sure they all have colliders)

public class Selecting : MonoBehaviour{

	private Color lastColor;

	private Transform GUI_object_refference;

		

	

	void Start(){

		//this is the empty gameobject on which you place your gui script

		GUI_object_refference = GameObject.Find("GUI_empty_game_object");

	}

	void OnMouseEnter(){

		//store the color of the material, and change it to red

		lastColor = transform.material.color;

		transform.renderer.material.color = Color.red;

	}

	void OnMouseExit(){

		//restore the color of the material

		transform.renderer.material.color = lastColor;

	}

	

	

	void OnMouseOver(){

		if(Input.GetMouseButtonDown("Fire1"){

			//we set the reference of the GUI script if we press the left mouse button on the object

			GUI_object_refference.GetComponent<GUI_Script>().SetRefference = gameObject;

		}

	}
}

And this script on an empty GameObject in the scene, named “GUI_empty_game_object” (without the commas), name it GUI_Script and write the next part of code inside it:

public class GUI_script : MonoBehaviour{

	//the refference variable

	private GameObject reference;

	

	//setter for the refference

	public GameObject SetReference{

		set { reference = value; }
	}

	void OnGUI(){
		if(GUI.Button(new Rect(100, 100, 100, 50), "ROTATE->")){
			if(reference){
				reference.transform.eulerAngles += new Vector3(0, 1, 0);
			}
			else{
				Debug.Log("There is no reference!");
			}
		}
		//do more buttons like this with different functions
	}
}

NOTE: I did not test this and this code is in C#, have fun tweaking it and making it work, if it doesn’t already :slight_smile:

oh thank you so much ar0nax.
I was just trying to code something from what you and exiguous advised me, but it was not working
(only one object was always affected by script) so I was just to post my crappy code to ask what was wrong.

Okay I’m gonna seriously study your last post and come back if still have issues.
thanx again

mmm…

well the console send me error messages when I just saved the first script :

Select.cs(43,53): error CS1525: Unexpected symbol `{’
Select.cs(52,1): error CS8025: Parsing error

Can’t figure out where the trouble is. I don’t see any disturbing or missing brace.

OK, this point solved. The actual issue was not “{” but a “)” that was missing.

Though, I now get another error message : The type or namespace name `MonoBehaviour’ could not be found. Are you missing a using directive or an assembly reference?

add this at the very beginning of each script, and make sure the script names are the same as class names, and they are all C# scripts.

using UnityEngine;
using System.Collections;

wow…

huh it’s even worse.

Now all these :

Selecting.cs(18,17): error CS0029: Cannot implicitly convert type UnityEngine.GameObject' to UnityEngine.Transform’
Selecting.cs(26,39): error CS1061: Type UnityEngine.Transform' does not contain a definition for material’ and no extension method material' of type UnityEngine.Transform’ could be found (are you missing a using directive or an assembly reference?)
Selecting.cs(46,26): error CS1502: The best overloaded method match for UnityEngine.Input.GetMouseButtonDown(int)' has some invalid arguments* *Selecting.cs(46,26): error CS1503: Argument #1’ cannot convert string' expression to type int’
Selecting.cs(50,74): error CS1061: Type GUI_Script' does not contain a definition for SetRefference’ and no extension method SetRefference' of type GUI_Script’ could be found (are you missing a using directive or an assembly reference?)

And yes I did check that script names and class names are exactly the same + saved scripts as .cs and not .js

So sorry for that… and with C# there is litteraly nothing I can do or understand.
I’m just trying to see if I can translate this in javascript but my knowledge is so low there…

edit : ok solved one at least the very last error line
This was due to a different spelling betwen both the 2 codes (SetRefference vs SetReference)

some new…

seems if(Input.GetMouseButtonDown(“Fire1”)) caused trouble.
I replaced it by if(Input.GetMouseButtonDown(0)), according to what the manual seems to say (about javascript though).

Now still “only” 2 error lines :

Selecting.cs(17,17): error CS0029: Cannot implicitly convert type UnityEngine.GameObject' to UnityEngine.Transform’
Selecting.cs(25,39): error CS1061: Type UnityEngine.Transform' does not contain a definition for material’ and no extension method material' of type UnityEngine.Transform’ could be found (are you missing a using directive or an assembly reference?)

ok now that’s better :

I replaced

private Transform GUI_object_refference;

by

private GameObject GUI_object_refference;

and I deleted (for the moment) all lines relative to materials.

And well the movement stuff works fine.
Still need to work but yet this is very close to what I’m looking for. Thank you very much.

replace this line private Transform GUI_object_refference; with this one: private GameObject GUI_object_refference; (you got it before my answer).

and instead of this: transform.renderer.material.color = Color.red;

try writing this:

foreach(Material go in transform.renderer.GetComponentInChildren(typeof(Material))){
	go.color = Color.red;
}

and instead of transform.renderer.material.color = lastColor;

write this:

foreach(Material go in transform.renderer.GetComponentInChildren(typeof(Material))){
	go.color = lastColor;
}

---------edit--------
i did not test the code, and wrote it in notepad, no compiler…

ar0nax,

just one more thing that really disturbs me.

See the sample here to understand :
http://www.chantiergraphique.com/CUBEH/

You click on red cubes (nothing happens visibly with Mouse Over as I deleted all material that did not work I don’t know why) but the “recording” of the reference works.

Then click on X, Y or Z button (3 rotation axis).
As you see it makes the selected cube rotate 90 ° (setted a color per face so that it’s understandable).

BUT the very strange thing is that X button only switches between 0 and 90 degrees (on X axis of course) while Y and Z buttons correctly go from 0, to 90, then 180, then 270 and back to 0 degrees.

I don’t understand why. Code is exactly the same for each.

void OnGUI(){
		if(GUI.Button(new Rect(100, 100, 50, 50), "X")){
			if(reference){
				reference.transform.eulerAngles += new Vector3(90, 0, 0);
			}
			else{
				Debug.Log("No reference");
			}
		}
		if(GUI.Button(new Rect(150, 100, 50, 50), "Y")){
			if(reference){
				reference.transform.eulerAngles += new Vector3(0, 90, 0);
			}
			else{
				Debug.Log("No reference");
			}
		}	
		if(GUI.Button(new Rect(200, 100, 50, 50), "Z")){
			if(reference){
				reference.transform.eulerAngles += new Vector3(0, 0, 90);
			}
			else{
				Debug.Log("No reference");
			}
		}

Is there any Unity bug ?

oh, I see you just posted some stuff about materials. Thank you so much.
You’re saving me days of work/searching for this stuff (which I friendly do myself, no money involved…)

Sorry but material stuff still not works

this should be good hint to consult the documentation to look what transform contains and what not. and if you dont find a material in transform have look there where material is contained (hint it begins with ren and ends with derer). a little work of yourself can be expected?

i think the other errors are related. but in most cases the casue of the error is relative clear so you should be able to fix it yourself instead of bugging us with your compiler errors. see the given code as hint in pseudocode, not as perfectly working solution.

sorry mate I did something wrong there, it should’ve been Material go in transform.renderer.GetComponentsInChildren(typeof(Material))

But that will not help, since you wanna rotate the cubes. the thing you can do is render another Cube, with a transparent material, which is enabled only in the OnMouseOver(){} , so it will hover over your selected cube.

the thing with material.color is only for visible notification of the cube you are selecting and such.

make sure you look for Gimble Lock on youtube (since that can occur when working with EulerAngles and 90 degrees angles)

But that’s exactly what I did. I looked at the doc and fixed some of errors - including the one you quote about “UnityEngine.Transform”. And posted my result here to avoid you guys having to reply about it again and again.

I do try to bug people here as less as possible but you also know that Unity doc only speaks javascript and gives no example / hint of C# syntax. Lucky you are if have good developpement skills but mind that for low level dev people (like me) the doc does’nt say on every page “hehe when you write a “:” in javascript you will use a “=” in C#” or such things. I did not even know that “function” becomes “void” here, and did not even understand how a variable should be declared in this language.
So yes, console errors here give a relatively clear idea about where the issues seem to be but still, very simple compiling errors can take hours to fix due to lack of basics. Be sure I do my best to fix it myself anyway.

again, thanx for help and advices