0
\$\begingroup\$

The game objects move from the right to the left, via a separate, working script. I want them to be destroyed when they cross the left side of the camera. How do I delete instantiated game objects when they move off the left side of the camera?


I am using this script to spawn game objects:

// Use this for initialization
void Start () 
{
    InvokeRepeating ("spawnObject", this.spawnInterval, this.spawnInterval);
}

void spawnObject() 
{
        float y = Random.Range(objectMinX, objectMaxX);

        GameObject newObject = Instantiate (this.prefabToSpawn, 
            this.transform.position + new Vector3(30,y,-30), Quaternion.identity);

        if (newObject.transform.position.x < Camera.main.transform.position.x)
        {
            // neither the print nor Destroy gets called
            print("destroy");
            Destroy(newObject);  
        }
    }
\$\endgroup\$
  • \$\begingroup\$ @Gnemlock It doesn't destroy the object , the debug doesn't show too \$\endgroup\$ – MrRobot9 May 14 '17 at 4:34
  • \$\begingroup\$ It looks like you're trying to define a rule that the newObject should be destroyed at some later time, once it crosses an x threshold. That's not what this code does though: it spawns the object and immediately checks to see if it's too far left. If it's not too far left at that very moment, then this function runs to completion and the object lives on indefinitely. Does that describe the problem you're observing? If you want to destroy the object later then you need to pass that responsibility to another method, coroutine, or killbox script. \$\endgroup\$ – DMGregory May 14 '17 at 4:42
1
\$\begingroup\$

You actually have two problems, in your code. The first is that the objects are not destroying. The second is that, when they do destroy, they won't destroy in the intended place.

I feel it will be more helpful to solve each problem, separately. First we will get the objects to start destroying, then we will adjust the code to provide the correct position.


Getting your objects to correctly check the Destroy() condition

In the above code, you instantiate the object as newObject, and than check if it is past a certain position. As soon as this check completes, you lose your reference to that object. The spawnObject method only ever checks the position straight after instantiation. It appears that you intend to perform this check regularly, as you continue to move the object.

You say that you have a script attached to the object in charge of scrolling. We will use this script to perform the checks, instead. For the sake of example, we will say this script is called AutoScroll.

public class AutoScroll : MonoBehaviour
{
    void Update()
    {
        // Perform logic to move the object, first. That way, it trigers
        // Destroy() as soon as it oversteps its boundary.

        if(transform.position.x < Camera.main.transform.position.x)
        {
            Destroy(gameObject);
        }
    }
}

Getting your objects to meet the right Destroy() condition

Now we have your objects destroying, you might notice that they destroy in the middle of the screen. That is because your checking against Camera.main.transform.position.x. The camera projects forward, but the object itself is positioned right in the middle of the view port.

We could find the true position for directly off the screen in a couple of ways. The programmatic way would involve trigonometry, notably incorporating the angle of the view and the distance from the object to identify the exact position where the object disappears out of camera view. For a simple project, especially in Unity, this might be over-complicated for your requirements. There is a much simpler one; we measure it, in the editor.

Create a cube, and place it in the scene at the co-ordinates where an object would be created by your object spawner. With the game view visible, move it to the left until it is just off the screen. Assuming the cube is not parented to anything, this should give us an approximate x position for off-screen. Note that "off-screen" changes, slightly, with different resolutions. You may want to change resolutions, in order to ensure you are always off-screen.

I move my cube, in the editor, and ensure it is just off screen across all available resolutions in the game view. I than note the x value of the cubes Transform component.

In my example, I find the cube is just off the left of the screen at a reliable x position of -8.35. I have checked across a couple of resolutions, but I like to cover myself in these sort of situations, and it will not hurt if it moves a little bit more off the screen. I would use a value of -9 or -10. We than check against this direct value, instead of Camera.main.transform.position.x.

public class AutoScroll : MonoBehaviour
{
    public float dropoffPosition = -9f;

    void Update()
    {
        // Perform logic to move the object, first. That way, it trigers
        // Destroy() as soon as it oversteps its boundary.

        if(transform.position.x < dropoffPosition )
        {
            Destroy(gameObject);
        }
    }
}

Note that you would have to readjust your boundary value if you make edits to the position of the camera; notably, the size or field of view, the position, or the size or position of your actual game objects being destroyed.

\$\endgroup\$
  • \$\begingroup\$ Wouldn't attaching a collider as child of camera and subscribing to is OnCollisionExit be simpler and less error prone? Or at least it would not rely on so many factors such as object size, camera position and orientation. \$\endgroup\$ – wondra May 14 '17 at 12:20
  • \$\begingroup\$ The problem with any of such calculations is they are for points, not objects and can produce nasty errors. Typically it is not a problem to place another object onto your camera rig - it will handle update with orientation and position changes, only FoV and scale will be problem(but why scale camera?), however if it is problem for your typical scene setup(s), dont trust unity's collision system or concerned about performance of adding a collider trigger, then checking x component is probably the way to go. \$\endgroup\$ – wondra May 14 '17 at 13:00
  • \$\begingroup\$ @wondra, as my answer shows, you would physically measure the number required for the if statement. The only room for error is in ones own understanding of maths (ergo why I do not provide an indepth trigonometric solution), and to be honest, the maths shown above is far more basic than is generally required for programming. Colliders work, but again, you would still need to account for any changes. Colliders will not wrap to the camera viewport; not unless you write additional code for the behavior. Again, no need to over complicate something that is incredibly simple in practice. \$\endgroup\$ – Gnemlock May 14 '17 at 14:23

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.