Elevating Enemy Movement in Unity: From Basic ZigZag to Advanced Patterns

Damian Dąbrowski
3 min readFeb 29, 2024

--

Creating engaging enemy behavior is a cornerstone of compelling game design. A classic approach to making enemies unpredictable is implementing a ZigZag movement pattern. Initially, we might start with a straightforward method, but as we refine our game, we seek smoother and more sophisticated movement strategies. Let’s explore how we can evolve a basic ZigZag movement into something more advanced, comparing the original method with improved implementations.

The Basic ZigZag Method

Initially, our ZigZag movement relies on direct position checks and abrupt direction changes. This approach is simple and easy to implement but can result in mechanical and predictable enemy behavior.

void ZigZagMovement() 
{
if (transform.position.x > _startXPosition + 2.0f)
{
direction = new Vector3(-1f, -1f, 0);
}
else if (transform.position.x < _startXPosition - 2.0f)
{
direction = new Vector3(1f, -1f, 0);
}
transform.Translate(direction * _speed * Time.deltaTime);
}

This method checks the enemy’s position relative to its start position and flips direction when it exceeds a certain threshold. While functional, this pattern can feel stiff and predictable.

Improved ZigZag: Sine Wave Approach

To achieve a smoother ZigZag movement, we can utilize the properties of a sine wave. This method offers continuous, fluid motion and allows easy adjustments to the pattern’s amplitude and frequency.

[SerializeField]
private float frequency = 5.0f; // Speed of sine movement
[SerializeField]
private float magnitude = 0.5f; // Width of sine movement

private float elapsedTime = 0;
void ZigZagMovement()
{
elapsedTime += Time.deltaTime;
float x = _startXPosition + Mathf.Sin(elapsedTime * frequency) * magnitude;
float y = transform.position.y - (_speed * Time.deltaTime);
transform.position = new Vector3(x, y, transform.position.z);
}

By applying a sine function, we create a natural, smooth oscillation in the enemy’s movement, enhancing the gameplay experience with more dynamic and less predictable patterns.

Simplified and Flexible: The Mathf.PingPong Solution

Another method to simplify the ZigZag movement while maintaining adjustability is using the Mathf.PingPong function. This approach automates the oscillation process, making the code cleaner and the movement pattern easier to tweak.

[SerializeField]
private float range = 2.0f;

void ZigZagMovement()
{
float x = Mathf.PingPong(Time.time * _speed, range) - (range / 2) + _startXPosition;
transform.position = new Vector3(x, transform.position.y - (_speed * Time.deltaTime), transform.position.z);
}

With Mathf.PingPong, we achieve a back-and-forth motion that is both easier to manage and modify, providing a versatile tool for creating engaging enemy behavior.

Comparison and Conclusion

The original ZigZag method serves as a functional starting point but lacks the fluidity and flexibility that can enhance a player’s experience. By transitioning to a sine wave approach, we introduce smoother, more natural movement patterns that add depth to enemy behavior. Furthermore, employing Mathf.PingPong simplifies the implementation and offers an efficient way to create dynamic and adjustable movement patterns.

In summary, while the basic ZigZag method is a good introduction to enemy movement patterns, exploring advanced techniques like sine waves and Mathf.PingPong can significantly improve the gameplay experience, making enemies feel more lifelike and unpredictable. Experiment with these methods to find the perfect blend of challenge and engagement for your game.

--

--

Damian Dąbrowski
Damian Dąbrowski

Written by Damian Dąbrowski

Hi, I’m Damian, an Electrical Power Engineer, who loves building AI powered apps.

No responses yet