Enemy Movement Patterns for Unity 2D Shooting Games: Easy to Implement and Enhance Gameplay
Great work, everyone!!
I was thinking about what kind of enemy movements to use for the shooting game I’m currently developing, and when I asked ChatGPT, it suggested several patterns that seemed immediately usable — so I thought I’d share them with you all!
Table of Contents
Basic Movement Pattern
① Straight-Line Movement (Top → Bottom)
- Description: Simply moves straight downward
- Difficulty: ★☆☆☆☆
- Best used in: Tutorial or early stages
transform.Translate(Vector2.down * speed * Time.deltaTime);
② Moves Downward While Swaying Left and Right (Wave Movement)
- Description: Moves in a zigzag pattern, making it harder to dodge bullets
- Difficulty: ★★☆☆☆
- Best used for: Mid-game and later stage minor enemies
float x = Mathf.Sin(Time.time * frequency) * amplitude;
transform.position += new Vector3(x, -speed * Time.deltaTime, 0);
③ Slowly Tracks the Player
- Description: Gradually approaches the player’s position
- Difficulty: ★★★☆☆
- Best used for: Enemies that create a sense of tension
Vector3 dir = (player.position - transform.position).normalized;
transform.position += dir * speed * Time.deltaTime;
④ Changes Direction Randomly (Unpredictable Movement)
- Description: Changes movement direction at set intervals
- Difficulty: ★★★☆☆
- Best used for: Ambush-type enemies
// At regular intervals
randomDir = new Vector2(Random.Range(-1f, 1f), -1f).normalized;
transform.position += (Vector3)randomDir * speed * Time.deltaTime;
With Action Pattern
① Approach → Explode
- Description: Approaches the player and self-destructs
- Difficulty: ★★★★☆
- Best used for: High-risk, charge-type enemies
public float speed = 2f;
public float explodeRange = 1.5f;
public GameObject explosionEffect;
private Transform player;
void Start()
{
player = GameObject.FindWithTag("Player").transform;
}
void Update()
{
if (!player) return;
Vector3 direction = (player.position - transform.position).normalized;
transform.position += direction * speed * Time.deltaTime;
if (Vector3.Distance(transform.position, player.position) < explodeRange)
{
// Explosion process
Instantiate(explosionEffect, transform.position, Quaternion.identity);
// If you want to deal damage to the player, do it here.
Destroy(gameObject);
}
}
② Appears from Behind → Disrupts Player’s Progress
- Description: Appears from behind, not above the camera, and pursues the player
- Best used for: Mid-boss type enemies that create tension
public float speed = 2f;
private Transform player;
void Start()
{
player = GameObject.FindWithTag("Player").transform;
}
void Update()
{
if (!player) return;
Vector3 direction = (player.position - transform.position).normalized;
transform.position += direction * speed * Time.deltaTime;
}
③ Flies in Formation (Formation Type)
- Description: Multiple enemies appear together in a formation
- Examples: V-shape, vertical line, horizontal line, circle
- Best used for: Visually appealing, also great for bonus stages
public float speed = 2f;
public Vector3 offsetFromLeader;
private Transform formationCenter;
void Start()
{
formationCenter = GameObject.Find("FormationLeader").transform;
}
void Update()
{
if (!formationCenter) return;
Vector3 targetPos = formationCenter.position + offsetFromLeader;
transform.position = Vector3.Lerp(transform.position, targetPos, Time.deltaTime * speed);
}
Special Patterns for Bosses
① Stops at Regular Intervals to Scatter Bullets
- Description: Stops to fire rapidly → Moves → Fires rapidly again
- Best used for: Mini-bosses, boss battles
public float moveSpeed = 2f;
public float moveDuration = 2f;
public float stopDuration = 1f;
public GameObject bulletPrefab;
private float timer;
private bool isMoving = true;
void Update()
{
timer += Time.deltaTime;
if (isMoving)
{
transform.Translate(Vector2.down * moveSpeed * Time.deltaTime);
if (timer >= moveDuration)
{
isMoving = false;
timer = 0;
InvokeRepeating(nameof(Shoot), 0f, 0.2f); // Scatter bullets
}
}
else
{
if (timer >= stopDuration)
{
isMoving = true;
timer = 0;
CancelInvoke(nameof(Shoot));
}
}
}
void Shoot()
{
Instantiate(bulletPrefab, transform.position, Quaternion.identity);
}
② Movement Pattern Changes Across Multiple Phases
Example:
- Phase 1: Straight-line movement + Single bullet
- Phase 2: Wave movement + Spread bullets
- Phase 3: Homing movement + Rapid fire
public enum Phase { Phase1, Phase2, Phase3 }
public Phase currentPhase = Phase.Phase1;
public float hp = 100;
public GameObject bulletPrefab;
public Transform player;
void Update()
{
switch (currentPhase)
{
case Phase.Phase1:
MoveStraight();
if (hp < 70) ChangePhase(Phase.Phase2);
break;
case Phase.Phase2:
MoveWave();
if (hp < 30) ChangePhase(Phase.Phase3);
break;
case Phase.Phase3:
MoveChase();
break;
}
}
void MoveStraight()
{
transform.Translate(Vector2.down * Time.deltaTime * 2f);
// Fire bullets slowly
}
void MoveWave()
{
float x = Mathf.Sin(Time.time * 2f) * 3f;
transform.position += new Vector3(x, -1f, 0f) * Time.deltaTime;
// Shoot spread bullets
}
void MoveChase()
{
Vector3 dir = (player.position - transform.position).normalized;
transform.position += dir * Time.deltaTime * 3f;
// Rapid fire attack
}
void ChangePhase(Phase next)
{
currentPhase = next;
Debug.Log("Phase transition:" + next);
}
public void Damage(float damage)
{
hp -= damage;
}
Additional Notes
- Enemy movement can be handled either in the Update method or by using Rigidbody2D’s velocity.
- Managing patterns with ScriptableObjects or Enums makes it easier to extend.
- For the bullets (bulletPrefab), set the behavior (such as straight movement, spread, etc.) in a separate script.。
Summary
This time, I shared some enemy movement patterns for Unity 2D shooting games that are easy to implement and enhance gameplay!
ChatGPT, who instantly suggested so many patterns, is really amazing!
I’m always grateful for the help! It’s like having a companion for game development (laughs).
2025-06-22
0件のコメント
コメントはまだありません。最初の一人になりましょう!