0
\$\begingroup\$

in the game I am doing atm you have an area with monsters. There are two modes to damage monsters :

  1. tapping on them
  2. casting spells on the ground

Tapping and damaging a monster works fine.

The problem : If I have selected a spell and want to cast it on the ground, the monster collider blocks my touch of the ground behind the monster.

My solution was to disable the monster collider when I want to cast a spell.

    GameObject[] toDisable = GameObject.FindGameObjectsWithTag ("Touch");

    foreach (GameObject g in toDisable) {
        g.GetComponent<Collider>().enabled = active;
    }

And ... it works.

Now my question is : Is this an adequate solution? They say GetComponent is slow, but I guess with 20 to 30 monsters running around it should be fine? Anything else that could be done? Maybe there is some Unity magic I am not aware of.

\$\endgroup\$
  • \$\begingroup\$ You could store a reference to these colliders on start, or when you instantiate the monster. Then use them from there. Even if you do it this way, how many components does the monster have? Probably not more than 10. A linear search through 30 of them should be nothing, especially if this is only for one frame. I'd be more worried about the FindGameObjectsWithTag method. \$\endgroup\$ – Ben May 4 '15 at 13:43
  • \$\begingroup\$ You are right, I should cache those gameobjects somewhere... but It's not a difference if I do GetComponent<Collider>() or GetComponent<ScriptWithReferenceToCollider>() on the gameobject afaik... \$\endgroup\$ – ElDuderino May 4 '15 at 15:15
  • \$\begingroup\$ No, cache the reference to the collider component itself. \$\endgroup\$ – Ben May 4 '15 at 15:23
  • \$\begingroup\$ I tried with the layermask and it works. See my answer below. \$\endgroup\$ – ElDuderino May 5 '15 at 8:34
1
\$\begingroup\$

The problem : If I have selected a spell and want to cast it on the ground, the monster collider blocks my touch of the ground behind the monster.

No need to disable colliders. Just assign different layers to monsters, spells and ground. Then use the collision matrix to specify that a spell doesn't collide with monsters.

(The same process, using LayerMask if you are using RayCasting)

They say GetComponent is slow, but I guess with 20 to 30 monsters running around it should be fine?

It's slow because there's no caching of Components in the Mono side of the scripts. Every GetComponent is forwarded to the native code which iterates through all components attached to a given GameObject. More objects, more calls. More components more thing to iterate through.

Definitely an overkill in this specific context.

| improve this answer | |
\$\endgroup\$
  • \$\begingroup\$ Hey, thanks for the response. To clarify, I am using the IPointerClick interface, and both my monster and my ground implement it. I have a physics raycaster at my camera. Monster and ground are at different layers. Both monster and ground receive the clicks, but the ground obviously doesn't when a monster is there. The "skill" at this point is just a bool signaling I want to hit the ground, not the monster. So It's not about colliding gameobjects. The physics raycaster has an event mask, should I change this to floor only at keypress? Will this work? Sry for the inconvenience :) \$\endgroup\$ – ElDuderino May 4 '15 at 15:04
  • \$\begingroup\$ I just had a quick test with the raycaster eventmask and it seems to work... \$\endgroup\$ – ElDuderino May 4 '15 at 15:07
  • \$\begingroup\$ Sorry, I can't help with UI classes. I still didn't dig into them, so I have no idea how IPointerClick is supposed to work. In general, I think if that part of the engine is coherent with the rest (and probably this is the case), you should be able to filter raycasting using layers. \$\endgroup\$ – Heisenbug May 4 '15 at 15:25
  • \$\begingroup\$ I tried with the layermask and it works. See my answer below. \$\endgroup\$ – ElDuderino May 5 '15 at 8:34
1
\$\begingroup\$

I think I have a solution: Set the LayerMask of the PhysicsRaycaster accordingly.

public LayerMask normal; //Everything
public LayerMask attack; //Floor
public PhysicsRaycaster rayCaster;

void Update() {

    attackAllowed = Input.GetKey (KeyCode.Space);

    rayCaster.eventMask = attackAllowed?attack:normal;

}

Works like a charm.

| improve this answer | |
\$\endgroup\$
  • \$\begingroup\$ glad you find a suitable solution for your specific needs :) \$\endgroup\$ – Heisenbug May 5 '15 at 9:32

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.