- Home /
How do I move only one selected object, rather than all objects with that script?
Been looking at a number of tutorials and forum questions, but I haven't been able to find the right answer to this one yet.
I'm working on a game where the level is filled with movable objects that can be translated up or down by the player. When the movement script is placed on one object and mouse click, it works the way it should. But if I put the script in all objects that need it and mouse click over an object, it moves all objects simultaneously. I'd imagine that raycasting is necessary, but I'm not too sure how to go about it in this case. Here's the current script:
void Update()
{
if (Input.GetMouseButtonDown(0))
{
GetComponent<Rigidbody2D>().velocity = new Vector2(0, forceInstant);
}
if (Input.GetMouseButtonDown(1))
{
GetComponent<Rigidbody2D>().velocity = new Vector2(0, -forceInstant);
}
}
Sorry if this seems like a dumb question; still learning Unity & C# so please forgive me if this has a simple solution (I'll probably be on here a lot). Thank you!
Answer by iabulko · Sep 15, 2016 at 06:25 AM
Raycasting isn't so hard as you imagine ;). Do not add script to all of the objects, just add it to one (i.e. called MainScripts ;p)
if (Input.GetMouseButton (0))
{
Vector2 mousePosition = Input.mousePosition;
RaycastHit hit;
Ray ray = Camera.main.ScreenPointToRay(mousePosition);
if(Physics.Raycast(ray, out hit, float.MaxValue))
{
actuallyHandledTra = hit.transform.GetComponent<Rigidbody2D>().velocity = new Vector2(0, forceInstant);
}
}
Answer by FlyingFlambe · Sep 16, 2016 at 11:36 AM
Thank you @iabulko! I had to fiddle with a few things since it's 2D not 3D, but I was curious on how to add the script to MainScripts and load it from there, rather than adding it to the object. Here's the current code as it is now (descriptions are there for clarity on my own part):
void Update()
{
//Instant force.
if (Input.GetMouseButtonDown(0))
{
//Creates a vector that holds location of the mouse pointer.
Vector2 mousePosition = Input.mousePosition;
//Creates a raycasthit variable to detect when mousePosition hits an object.
RaycastHit2D hit = Physics2D.Raycast(Camera.main.ScreenToWorldPoint(Input.mousePosition), Vector2.zero);
//If the hit ray hits an object's collider...
if (hit.collider != null)
{
//Add forceInstant to the gameObject.
hit.collider.gameObject.transform.GetComponent<Rigidbody2D>().velocity = new Vector2(0, forceInstant);
}
}
With the way it is right now, it moves only one object (which is what I wanted!), but it's able to move any object with a Rigidbody2D, including the player object. How would I use something like CompareTag to only move objects with that specific tag? (Also, should I ask this question on a different post next time? :x) Again, your response helped me a lot. Thank you!
You can always check it by name or tag
//If the hit ray hits an object's collider...
if (hit.collider != null)
{
//Add forceInstant to the gameObject.
if(hit.collider.gameObject.CompareTag("ObjectTagThatINeedToClick"))
hit.collider.gameObject.transform.GetComponent<Rigidbody2D>().velocity = new Vector2(0, forceInstant);
}
Thank you! Was trying to figure out how to format the CompareTag part but kept getting it wrong, so that helped a good bit. :)
Thanks FlyingFlambe, I was trying this since past 6 hrs and your code really helped me. (Tu khuda ka baccha hai (God's child)!!!)
Answer by Adarn · Sep 16, 2016 at 01:47 AM
An alternative to using a ray cast is the OnMouseDown() from monoBehaviouor
https://docs.unity3d.com/ScriptReference/MonoBehaviour.OnMouseDown.html
So a quick solution would be to change
void Update()
to
void OnMouseDown()
This way you can put your script on all the objects you want this behaviour on (like you already have done), but it only gets called on the objects you actually click on.
The body of your function should be okay as is, but you may need to change it slightly if you want it to run if the mouse button is held. I think this function only fires for the on press.
Thanks @Adarn. Using On$$anonymous$$ouseDown() would likely be useful in most cases, but been trying it out and doesn't seem to do what it needs to, since there's a few mouse commands that overlap (more explained at the end).
The main issue that needs to be fixed now is to not move just any rigidbody-- while this script exist in the game object its supposed to pertain to. With how it is right now, if I put the script on the correct object, the force command in that script can be applied to any object with a rigidbody which is kind of strange.
I'll also ask this part in another question later since its off-topic (and because its not really working right), but for clarity's sake on why On$$anonymous$$ouseDown() won't work too well: the game makes heavy use of the mouse buttons so the big issue right now is how the mouse commands overlap one another. Here's how I'm currently trying to set them up:
[Standard Force - Up] Left click (held down): applies an upward s$$anonymous$$dy acceleration via incremental additive force
[Standard Force - Down] Right click (held down): applies a downward s$$anonymous$$dy acceleration via incremental additive force
[Instant Force - Up] Left click (release): applies an upward high-impact force via one-time force + current velocity
[Instant Force - Down] Right click (release): applies a downward high-impact force via one-time force + current velocity
Hopefully that gives some insight on my current issue. I appreciate the feedback!
Oh, I also just caught this. When I try to run the build, it creates tens (or hundreds) of the same error saying the script is trying to access objects without a rigidbody. So something strange is definitely going on that I can't figure out.
Your answer
Follow this Question
Related Questions
Hit is always returning null for some reason. 1 Answer
2D - finding object at mouse position 2 Answers
Dynamic mesh positioning with Raycast intersection... 0 Answers
Raycasting2D to Compare Tag of GameObject 1 Answer
Raycast Not Working 3 Answers