问题
If I have a trigger or collision I want to target that gameObject and have access to it's properties for each of the attached scripts. I managed to do it like this but I know there has to be a better method right?
Here I wanted to target the script attached to the triggered game object labeled "BoxManager" and then BoxManager's property "isHeld" If the target is being selected dynamically like this when it interacts with the trigger/collision I have to use the target object, but is there a better way to do the rest?
void OnTriggerStay2D(Collider2D target)
{
if (target.gameObject.tag == "Box")
{
if (target.attachedRigidbody.GetComponent<BoxManager>().isHeld == false)
{
target.attachedRigidbody.AddForce(transform.right * thrust);
}
}
}
回答1:
First of all, target.attachedRigidbody.GetComponent<BoxManager>() is totally unnecessary and redundant. I've seen people even do worse with code such as target.attachedRigidbody.gameObject.transform.GetComponent<BoxManager>();. That's doing the-same thing because they are all attached to one GameObject.
You can and should simply that to target.GetComponent<BoxManager>();.
As for using GetComponent function all the time to get another script during collision, that's fine. It is the easiest way to get another Script that is attached to the GameObject during collision before you can access the variables in side that script.
Although, I find it annoying that you must do GetComponent in the OnTriggerStay2D just for that. It get's more annoying when you have so many scripts to check.
This is your collision function:
void OnTriggerStay2D(Collider2D target){}
And you need to access your BoxManager script from target after collision....
A tricky way would be to use a Dictionary. In the Start function initialize the Dictionary and use Collider2D as the key and BoxManager as the value.
Update this Dictionary when you instantiate and destroy GameObjects with Collider2D and BoxManager during game-play.
Something like this:
Dictionary<Collider2D, BoxManager> scriptID = new Dictionary<Collider2D, BoxManager>();
Then inside your collision function, use TryGetValue and the target variable as the key to get the BoxManager component.
void OnTriggerStay2D(Collider2D target)
{
if (target.CompareTag("Box"))
{
BoxManager result;
scriptID.TryGetValue(target, out result);
if (!result.isHeld)
{
}
}
}
In fact, if you %100 sure that this object has the BoxManager script attached to it, you can do that in one line of code with without the TryGetValue function:
void OnTriggerStay2D(Collider2D target)
{
if (target.CompareTag("Box"))
{
BoxManager result = scriptID[target];
}
}
You can reduce the chances of detecting Object without the BoxManager script by using target.CompareTag like above. Notice how I changed your target.gameObject.tag to target.CompareTag. It recommended to use target.CompareTag.
Now the code has been simplified with BoxManager result = scriptID[target]; while using target.CompareTag("Box") as a guard so that you don't have to use TryGetValue or the ContainsKey function.
Below is what the example of the whole script should look like:
Dictionary<Collider2D, BoxManager> scriptID = new Dictionary<Collider2D, BoxManager>();
public BoxManager boxManagerPrefab;
void Start()
{
//Register your BoxManager instances to the Dictionary
for (int i = 0; i < 5; i++)
{
BoxManager bc = Instantiate(boxManagerPrefab) as BoxManager;
//Use Isntance ID of the Script as id
Collider2D cld2D = boxManagerPrefab.GetComponent<Collider2D>();
scriptID.Add(cld2D, bc);
}
}
void OnTriggerStay2D(Collider2D target)
{
if (target.CompareTag("Box"))
{
BoxManager result = scriptID[target];
if (!result.isHeld)
{
target.attachedRigidbody.AddForce(transform.right * thrust);
}
}
}
来源:https://stackoverflow.com/questions/43934277/simplest-way-to-target-gameobjects-properties-when-it-triggers-collides