Factory Pattern is very popular if you are looking for creating kind of same objects with different properties for example implementing additional properties to factorized game object like adding different colors abilities
Most important step is to create a good factory class which can be implemented in to most different situations I prefer a static class with generic option because there can be different objects it completely isolates from other classes.
One certain property is imprtant in our example its "Name" property name of prefab or game object to create from factory
In Our example thjere are different type of buildings "House","Office","Government" buildings they both have same properties and some of them may change.
PackageLink is here ClickTo Download
I started with a building FactoryGenerator Class
using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using UnityEngine;
public static class FactoryGenerator<T> where T : class
{
// Name of prefab or game object
private const string NAME = "Name";
// dictionary for keeping created factories and find by name when its needed
private static Dictionary<string, T> factoryTypesByName;
// check if system started by a simple null check
private static bool isinitialized = factoryTypesByName != null;
public static void InitializeFactoryGenerator()
{
// if started no need to work code again
if (isinitialized) { return; }
// creawte instance of dictionary to add
factoryTypesByName = new Dictionary<string, T>();
// get all the factories which arent abstract and child of our main class provided with (T)
// this line uses System.Linq
var factoryTypes = Assembly.GetAssembly(typeof(T)).GetTypes().Where(x => x.IsClass && !x.IsAbstract && x.IsSubclassOf((typeof(T))));
foreach (var type in factoryTypes)
{
//Creates instance of subclass
var factory = Activator.CreateInstance(type) as T;
// get Name property of class as string
var rslt = factory.GetType().GetProperty(NAME).GetValue(factory) as string;
// add to Dictionary
factoryTypesByName.Add(rslt, factory);
}
}
///
/// calls from factory by PrefabName
///
///
///
public static T CreateObject(string Code)
{
// get first macth of class and return as class
return factoryTypesByName.Where(v => v.Key == Code).Select(x => x.Value).FirstOrDefault();
}
}
=> And Main FactoryClass as a base class to other factory classesusing System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public abstract class Buildings:MonoBehaviour
{
public abstract string Name { get; }
// property of a building
public abstract Color buildingColor { get; }
// sample creation of building
public virtual void CreateBuilding()
{
/// creates object based on name
GameObject gmObj = Resources.Load(this.Name) as GameObject;
Instantiate(gmObj);
gmObj.transform.position = Vector3.zero;
}
}
public class Office : Buildings
{
public override string Name => "Office";
public override Color buildingColor => Color.red;
public override void CreateBuilding()
{
base.CreateBuilding();
}
}
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class House : Buildings
{
public override string Name => "House";
public override Color buildingColor => Color.green;
public override void CreateBuilding()
{
base.CreateBuilding();
}
}
using System.Collections;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class Government : Buildings
{
public override string Name => "Government";
public override Color buildingColor => Color.blue;
public override void CreateBuilding()
{
base.CreateBuilding();
}
}
=>"CreateFromFactory" Class is should be like below
public class CreateFromFactory : MonoBehaviour
{
private void Start()
{
// setup building factory;
FactoryGenerator<Buildings>.InitializeFactoryGenerator();
}
public void CreateOffice()
{
this.CreateFactory("Office");
}
public void CreateHause()
{
this.CreateFactory("House");
}
public void CreateGovernment()
{
this.CreateFactory("Government");
}
private void CreateFactory(string name)
{
Buildings rslt = FactoryGenerator<Buildings>.CreateObject(name);
rslt.CreateBuilding();
}
}=>ResultIts normal you may think like why arent be just instantiating objects yes it can be made butto manage every object in game and gaining control over properties e specially when you have same object with different proprerties this approach cames in handyand keeps your much cleaner and readable every timeAlso improves reuseablity of code with different projects.Happy Coding

No comments:
Post a Comment