Abstracting the movement of enemies

Hello everyone,

I asked this question on Unity Answers but it was rejected and it was suggested I come here instead, so here I am :slight_smile:

I have a small problem. To teach myself Unity I have made a simple Missile Command game. While it works pretty well, I’ve been in the field long enough to know that not because it works that it is done well. The way I built my enemies and missiles is that they share the same movement class which is rather straightforward, since the they only need a target and both will make their way towards it the same way. Here it is:

    using UnityEngine;
    using System.Collections;
  
    public class Movement : MonoBehaviour
    {
        public float speed;
  
        [HideInInspector]
        public Vector2 target;
  
        void Start()
        {
            Vector3 dir = new Vector3(target.x, target.y, -10) - transform.position;
            float angle = Mathf.Atan2(dir.y, dir.x) * Mathf.Rad2Deg;
            transform.rotation = Quaternion.AngleAxis(angle - 90, Vector3.forward);
        }
  
        void FixedUpdate()
        {
            float step = speed * Time.deltaTime;
            transform.position = Vector2.MoveTowards(transform.position, target, step);
        }
    }

The missiles also use this movement class but for them the target is where the mouse clicked. And here is the Enemy class:

    using UnityEngine;
    using Random = UnityEngine.Random;
    using System.Collections;
  
    public class Enemy : MonoBehaviour {
        private Movement mov;
        private CriticalHit ch;
  
        public string enemyName;
        public int pointValue;
  
        // Use this for initialization
        void Start () {
            mov = GetComponent<Movement>();
            mov.target = new Vector2(Random.Range(0f, 10f), -5);
  
            ch = GetComponent<CriticalHit>();
        }
  
        void OnTriggerEnter2D(Collider2D other)
        {
            if (other.gameObject.tag == "City")
            {
                other.gameObject.GetComponent<City>().Hit(ch.criticalChance, ch.criticalMultiplier);
  
            }
            else if (other.gameObject.tag == "Enemy")
            {
                return;
            }
  
            Death();
        }
  
        public void Death()
        {
            Destroy(this.gameObject);
        }
      
        public void Intercepted () {      
            GameManager.instance.UpdateScore(pointValue);
            Death();
        }
    }

This allow me to just add the movement script to my enemies and missiles and specify a speed value. Now my problem is that I want to do another kind of enemies, one that is homing but I don’t want to have to remake another Enemy class since both will act the same way except for the movement pattern. I don’t really know where to start for this. My guess is that I should do an abstract Movement class with the basics of movements and then make other classes inherit from it for the specifics. I also feel that the target variable should be with the enemy and not with the movement class.

I just need a small nudge in the right direction and I feel I’ll be able to do this :slight_smile:

Thanks!

PS: English is not my main language and I tried to be as clear as I could, don’t hesitate to ask if you need more details.

There are many ways to go about this problem. The easiest way would probably be to inherit from Movement.

public class Homing : Movement {
//stuff
}

Also, you might want to mark your methods as virtual so you can override them.

Seems to me that your Movement class does three things:

  • find the current rotation
  • find the current direction
  • move

The two first are implementation specific, while the third one are common. So you probably want an abstract Mover, and a MoveStraight and MoveHoming class.

Then you have your Enemy and Missile scripts just call SetTarget, and you’re good to go.

You know, this is so clear now that I don’t know how I didn’t think about doing it this way before. Sometimes taking a step back or having a second opinion helps. Thanks a lot to you two, I’ll try it tonight when I get back home :slight_smile:

1 Like