1
\$\begingroup\$

I'm learning about Design Patterns using Unity and I'm not sure about how to solve the following problem with the Factory Method Pattern:

I want to read a XML file and using the Factory Method Pattern to create a Component (a Weapon) to add it to a GameObject which will be cointained on a Pool Manager, but Weapon "Is A" MonoBehaviour and for that reason It can't be instantiated using a "machineGun = new MachineGun();"

public abstract class WeaponFactoryMethod
{
    protected string fileName = "weapons.xml";
    public abstract Weapon CreateWeapon();
}

public class MachineGunFactoryMethod : WeaponFactoryMethod
{
    public override Weapon CreateWeapon()
    {
        string filePath = Path.Combine(Application.streamingAssetsPath, fileName);
        Weapon machineGun = null;
        XmlReader xmlReader = new XmlTextReader(filePath);
        if (xmlReader.ReadToDescendant("Weapons"))
        {
            if (xmlReader.ReadToDescendant("Weapon"))
            {
                do
                {
                    // I CAN'T DO THIS:
                    machineGun = new MachineGun();
                    machineGun.ReadXml(xmlReader);
                } while (xmlReader.ReadToNextSibling("Weapon"));
            }
            else
            {
                Debug.LogError("There aren't definition for Weapon");
            }
        }
        else
        {
            Debug.LogError("There aren't definition for any Weapon");
        }

        return machineGun;
    }
}

public abstract class Weapon : MonoBehaviour, IXmlSerializable
{
    public float AttackRange { get; set; }
    //Every weapons Shoots in a different way
    public abstract void Shoot();

    //Serialization
    public XmlSchema GetSchema()
    {
        return null;
    }

    public void ReadXml(XmlReader reader)
    {
        XmlReader childReader = reader.ReadSubtree();
        while (childReader.Read())
        {
            switch (childReader.Name)
            {
                case "AttackRange":
                    childReader.Read();
                    AttackRange = childReader.ReadContentAsInt();
                    break;
            }
        }
    }

    public void WriteXml(XmlWriter writer)
    {

    }
}

public class MachineGun : Weapon
{
    public override void Shot()
    {
        //Raycasting..
    }
}

At the end I want something like

GameObject (player)
 - Component (A Weapon script with the data from the xml)

Should I just create a GameObject (player) and do an "AddComponent < MachineGun >" and later copy the info from the xml file instead using the Factory Method Pattern??

Is there a better way??

Any suggestions, corrections or advice will be very grateful.

I'm sorry by my English.

\$\endgroup\$

1 Answer 1

0
\$\begingroup\$

You're just not supplying your factory with the right parts to do its job. You can learn about another design pattern called dependency injection. Essentially, you pass the GameObject you want to be modified into the factory as an argument.

public override Weapon CreateWeapon(GameObject target){
...
             machineGun = target.AddComponent<MachineGun>()
             machineGun.ReadXml(xmlReader);
...
}

This will add the component to the GameObject and then read the XML to configure the component.

\$\endgroup\$
2
  • \$\begingroup\$ This is embarrasing, that was so obvious, Thank you very much!!! \$\endgroup\$
    – user264560
    Commented Sep 21, 2017 at 1:38
  • \$\begingroup\$ Sure, you can accept the answer as correct if it solves your problem \$\endgroup\$
    – House
    Commented Sep 21, 2017 at 2:08

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .