Patrolling Sawbots

I tried something that I had not done before in Unity for this LD: Raycast2D. You can see the sawbot functioning, and don't forget to play and rate Specimen Delve, here.

What the Sawbots Do

The Sawbots are fairly simple automatons: they patrol back and forth on whatever block they are on, then if they run out of platform to walk on, they turn around. If they bump into something, they turn around. If they see something they can shoot, they stop moving and shoot. That was the general idea, and here's how it went.

Disclaimer: I'm describing what I did, which may or may not be ideal. Experts comment!

The Setup

The Sawbot is a single sprite with an empty GameObject floating out in front of it. To get it moving, I had a few booleans managing what the sawbot was doing, and then a simple translate to move it during FixedUpdate.

``` Vector2 facing; facing = (facingRight) ? transform.right : -transform.right; if (moving) { transform.Translate(facing * speed * Time.deltaTime);

    }

``` There's a small Flip function to rotate the sprite/gameobject as well. The full code is in the PatrolAI.cs script on github. Floating in front of the sprite is an empty GameObject that I aim a ray downward to look for ground ahead of it, and a ray forward to look for targets to shoot. You can see the rays and position below (which will likely be pulled in closer in a later build)

Looking at the Ground

SawbotAIRays.png

And here (but consolidated) are the functions that I used to detect the ground. The LayerMask contains all of the objects that could be ground, while the edgeDetect Transform is the Transform of the empty GameObject that was being used to look ahead at the ground. ``` public Transform edgeDetect;

public LayerMask lm; //looking for ground

    RaycastHit2D hit;
    hit = Physics2D.Raycast(edgeDetect.position, Vector2.down, 1, lm);
    Debug.DrawRay(edgeDetect.position, Vector2.down, Color.red);
    if (hit.collider != null)
    {
        hitGround = true;
        Debug.Log("Robot hit something.");
    }
    else
    {
        Debug.Log("Robot didn't see ground.");
        Flip();
        hitGround = false;
    }

```

Happy Accident Looking Down

This worked well while on a platform, and accidentally worked (sort of) when it walked into a wall, since it detects the wall ahead as ground. As the player froze objects, however, the Sawbot didn't flip. I added a Collision check and when the sawbot hit an object with the "Iceblock" tag, it would turn around.

private void OnCollisionEnter2D(Collision2D collision) { if(collision.gameObject.tag == "Iceblock") { Flip(); //Debug.Log("hit an iceblock"); } }

Unfortunately, after adding additional Sawbot spawning mechanics, I realized that I forgot to update the OnCollisionEnter2D function above, and the below behavior emerged: SawbotCollide.png Two Sawbots would run into each other indefinitely since they neither detected the Sawbot in the collision, or saw the other Sawbot with the ray. My first instinct was: FIX IT! Then, as I watched it happen a few more times, I realized that there was something amusing about these mindless drones running into each other indefinitely, because they were either malfunctioning or poorly programmed to begin with. I started trying to push Sawbots into these positions, and found that I could use their "programming" against them to harvest the level around them.

For me, this was a fun, unplanned, and emergent behavior that I decided to keep. See if you can use this technique against them and get deeper into the caverns in Specimen Delve over here.

My Takeaways

Overall, even though I wandered around the code to make these things function, I was able to get the patrolling, target detection, and shooting all to function with essentially the same technique. Cast our a Ray, determine what it hit, and take action. Having this tool in my back pocket opens up several options for me, and an unexpected number of uses in 2D.

Let me know what you think or what interesting things you may have used RaycastHit2D for. Thank you for reading!