Same script working for one object but not two.

Hello,

I have a flying enemy who is dropping an object ( it’s child ) every seconds. In this case all works fine but if I add a second flying enemy doing the same with the same script the first object will have a random position and will not be visible.

Here is the script that handle the drop mechanism :

public class UniP : MonoBehaviour {

    Collider2D rainbwp;
    public float speed;
    Vector3 pos;


	// Use this for initialization
	void Start () {
        rainbwp = GameObject.Find("rainbowplatform").GetComponent<Collider2D>();
	}
	
	// Update is called once per frame
	void Update () {


	}

    void Begin()
    {
        StartCoroutine(Whatever());
    }

    IEnumerator Whatever()
    {
        transform.position = transform.parent.transform.position; 
        gameObject.GetComponent<BoxCollider2D>().enabled = true;
        gameObject.GetComponent<SpriteRenderer>().enabled = true;
        gameObject.GetComponent<Rigidbody2D>().gravityScale = 2;
        yield return new WaitForSeconds(2);
        StartCoroutine(Whatever());
    }

    void OnCollisionStay2D(Collision2D other)
    {
        pos = other.contacts[0].point;

        if (other.collider == rainbwp)
        {
            gameObject.GetComponent<Rigidbody2D>().gravityScale = 0;
            transform.position = pos ;
        }
    }
}

Thanks for your help

Hi, I think the problem could be the line where you get the GameObject by name, and then get its Collider2D component:

rainbwp = GameObject.Find("rainbowplatform").GetComponent<Collider2D>();

If there is more than one GameObject with the same name I don’t think you can guarantee which will be returned. As a workaround you could make “rainbwp” public (or serialized) so that you can assign it in the inspector.

[SerializeField] Collider2D rainbwp;

That line will allow you to drag the collider that you want into the component in the inspector and you will no longer need the line in (or the entire method) “Start”.

I hope that helps =)

This issue is not likely completely to do with your script. There are a number of things I would suggest doing differently, but most of those would be improvements to readability and computational efficiency.

Given that I’m not going to give you a lecture on coding practices, and I’d much rather help you solve your issue, I’d have to start by asking where you are instantiating these enemies? When they start, are they being placed “inside” each other’s colliders? If so, the collision reaction could be pretty crazy, and might explain why one of them moves off to the end of the screen.

Next, what are these objects parented to? Do they have parents GameObjects? If not, I would bet that there are at least a few error messages, and if they do have parent GameObjects, what (if any) components are attached to those parents?

Also, have you checked the console for errors? If it’s really “invisible” then I imagine something is going wrong with the renderers, as well.

Try pressing the pause button before you start play mode, so it pauses the game after the first frame is evaluated. If the transforms are still in the proper places, then it’s the physics simulations overreacting because the colliders are overlapping too much.

Your coroutine seems like the only other place that might be causing this behavior, and I would strongly suggest against relying on coroutines for most situations, since there are many significantly more reliable and efficient methods of handling iteration over time that are more consistent with the coding standards that Unity has built up (such as timing through the update function, with Time.deltaTime, or by using FixedUpdate and Time.fixedDeltaTime, for higher precision timing).

But again, that’s more of a readability and cyclomatic complexity issue than anything, and I strongly suspect that something else about the scene composition is at least involved with this strange behavior.

Edit

Something I noticed- Nothing calls “Begin” or your coroutine, from this script, unless you have something sending a message or calling that method to the object, from another script?