问题
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