- Home /
Differentiating between seperate game objects in code when one script is attached to multiple game objects? (2D)
I am trying to make it to where selecting one crate gives you one item and selecting another crate gives you a different item. I am using a single script to handle all of this. I am attempting to tag game objects and using the CompareTag() function to attempt to differentiate between two crates. Here is the script I am currently using:
using UnityEngine;
using System.Collections;
public class CrateOpen : MonoBehaviour {
public bool crateOpenBool = false;
void FixedUpdate() {
GameObject player = GameObject.FindWithTag("Player");
RaycastHit2D hit = Physics2D.Raycast(Camera.main.ScreenToWorldPoint(Input.mousePosition), Vector3.forward);
Vector2 pos = player.transform.position;
float distance = Vector2.Distance(pos, hit.point);
if (hit.collider != null && Input.GetMouseButtonDown(1) && distance <= 2.0) {
// Area I am working with
if (CompareTag("pCrate")) {
Debug.Log ("pistol");
}
if (CompareTag("kCrate")) {
Debug.Log ("knife");
}
// Area I am working with
crateOpenBool = true;
} else if (hit.collider == null || distance > 2.0) {
crateOpenBool = false;
}
}
}
Answer by Kiwasi · Sep 30, 2014 at 08:30 PM
You could make this work simply by changing the problem lines to
if(hit.collider.tag == "pCrate");
However I feel obligated to point out a few other problems in your script.
You are getting input in FixedUpdate. This is generally a bad idea, as the Input class is modified during Update. Its possible to miss inputs this way
You are doing a raycast regardless of weather you use it or not. Raycasts are expensive, checking input is cheap. Only do the raycast if your input is present.
For ultimate versatility I would suggest having this script use SendMessage to tell the crate it is selected. Then have the crate take care of the instantiating. This will allow the script to be reused for selecting any object. It would also allow crates to be modified for a larger combination of results.
Edit: Just reread the question. You should only have a single copy of this script on one GameObject in the scene. Having a copy on every crate will just lead to inefficiencies and problems.
Sorry for the late response: but thanks! this works fine. But, if possible, would you $$anonymous$$d going into a bit more detail about how I could use Send$$anonymous$$essage in this situation? Thanks!
Sure. Some pseudo code to demonstrate the idea
Here is an input class. Attach it to the main camera. Or to a separate input manager. Or to the player. It really doesn't matter.
public class Input$$anonymous$$anager : $$anonymous$$onoBehaviour {
void Update (){
if(Input.Get$$anonymous$$ouseButtonDown(1)){
RaycastHit2D hit = Physics2D.Raycast(Camera.main.ScreenToWorldPoint(Input.mousePosition), Vector3.forward);
if(hit.collider){
hit.collider.Send$$anonymous$$essage("Clicked",Send$$anonymous$$essageOptions.DontRequireReciever);
}
}
}
}
Here is the crate class. Attach to a crate. You can set the item to whatever you like via the inspector
public class Crate : $$anonymous$$onoBehaviour {
public GameObject item;
public void Clicked (){
Instantiate (item, transform.position, transform.rotation);
Destroy(gameObject);
}
}
Where this really shines is when you want other things that can be clicked. Lets say your pistol. (Actually this would be better done in an item base class, or in an interface, but you get the idea.)
public class Pistol : $$anonymous$$onoBehavior {
public void Clicked (){
AddPistolToInventory ();
Destroy(gameObject);
}
}
And how about a door?
public class Door: $$anonymous$$onoBehavior {
private bool isOpen = false;
public void Clicked (){
isOpen = !isOpen;
}
}
And so forth. Essentially you are using one script to process your click and forward it to the right item. The item itself can then take care of the needed behaviour.
Send$$anonymous$$essage is more expensive then directly calling the method, as Unity has to go through all of the components of the GameObject to find your method. But for an input manager as you have described the ease of coding is worth it.
Answer by LSPressWorks · Sep 30, 2014 at 05:20 AM
I know this isn't the specific answer you are looking for, but if you simply create a string var in the script, you can change it on any object. This means any crate can have any itemIdentifier provided either at runtime or via the inspector.
ie(warning this is pseudo code, probably won't run without a little work.)
//------FROM AN OUTSIDE CLASS
import crateClass;
var caseToOpen : crateClass;
var itemRet : String;
OnCollisionEnter(thingy : collider)//or hits from a cast or whatever identifies the object to yank the function from. I think you used casts collider there. Either way.
{
//-- grab value from crate
caseToOpen = thingy.GetComponent("crateClass");
itemRet = caseToOpen.getItemTag();
}
//---------FROM WITHIN crate class
var itemtag : String;//--for later use it's wise to create an array/vector whatever
var wasPicked : boolean;
//etc etc etc
public function getItemTag() string
{
if(waspicked != true)
{
return this.ItemTag;
waspicked = true;
}else{return "Nada';}
}
at which point you assign at runtime or via the edi
From what you are describing you'd want. Otherwise you have the right idea, it's only the part you're grabbing the info from that may be causing you issues.
Answer by Tepei · Sep 30, 2014 at 07:23 PM
Maybe create a central script that have a static array.
inside the script you want to tag, on start function add a new value in the array.. CentralScript.number.Add(x); Then get the lenght of this array and you have a different number for all the same scripts..
numb =CentralScript.number.Lenght;
Your answer
Follow this Question
Related Questions
Multiple Cars not working 1 Answer
A node in a childnode? 1 Answer
Switching Cameras at runtime 1 Answer
Increase Jump Through Mouse Clicks? 1 Answer
2D Game - Y axis rotation (left - right) 2 Answers