(九)工厂模式(简单工厂、工厂模式和抽象工厂)
创建战士工厂:
创建ICharacterFactory工厂接口,和继承其的子类 SoldierFactory 和 EnemyFactory
在IWeapon中 声明枚举类 WeaponType 武器类型
在ICharacterAttri中对其构造函数进行改写,对其属性进行初始化(后续不做改变)
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public interface ICharacterFactory
{
//where T : new() 类型参数必须有一个公有、无参的构造函数。当于其它约束联合使用时,new() 约束必须放在最后。
ICharacter CreateCharacter<T>(WeaponType weaponType,Vector3 spawnPos,int lv =1)where T:ICharacter,new() ;
}
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class SoldierFactory : ICharacterFactory
{
public ICharacter CreateCharacter<T>(WeaponType weaponType, Vector3 spawnPos, int lv = 1) where T : ICharacter, new()
{
ICharacter character = new T();
//创建角色游戏物体
//1. 加载 2. 实例化 TODO
//添加武器 TODO
string mName;
int mMaxHp;
float mMoveSpeed;
string mIconSprite; // 资源加载
string mPrefabName;// 通过Prefab名字实例化Prefab
System.Type type = typeof(T);
if (type == typeof(SoldierCaptain))
{
mName = "上尉士兵";
mMaxHp = 100;
mMoveSpeed = 3;
mIconSprite = "CaptainIcon";
mPrefabName = "Soldier1";
}
else if (type == typeof(SoldierSergeant))
{
mName = "中士士兵";
mMaxHp = 90;
mMoveSpeed = 3;
mIconSprite = "SergeantIcon";
mPrefabName = "Soldier2";
}
else if (type == typeof(SoldierRookie))
{
mName = "新手士兵";
mMaxHp = 80;
mMoveSpeed = 2.5f;
mIconSprite = "RookieIcon";
mPrefabName = "Soldier3";
}
else {
Debug.LogWarning("战士类型["+type+"]不存在");
return null;
}
ICharacterAttr attr = new ICharacterAttr(new SoldierAttrStrategy(),mName,mMaxHp,mMoveSpeed,mIconSprite,mPrefabName);
character.CharacterAttri = attr;
return null;
}
}
创建资源工厂:
创建IAssetsFactory工厂接口,和继承其的子类RemoteAssetsFactory(从远程服务器更新加载资源),LocalAssetsFactory(从本地更新加载资源),ResourcesAssetsFactory(通过资源加载更新加载资源)
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public interface IAssetFactory
{
GameObject LoadSoldier(string name);
GameObject LoadEnemy(string name);
GameObject LoadWeapon(string name);
GameObject LoadEffect(string name);
AudioClip LoadAudioClip(string name);
Sprite LoadSprites(string name);
}
完善通过Resources加载的资源工厂 :
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class ResourcesAssetFactory : IAssetFactory
{
public const string SoldierPath = "Characters/Soldier/";
public const string EnemyPath = "Characters/Enemy/";
public const string WeaponPath = "Weapons/";
public const string EffectPath = "Effects/";
public const string AudioPath = "Audios/";
public const string SpritePath = "Sprites/";
public GameObject LoadEffect(string name)
{
return InstaniateGameObject(EffectPath+name);
}
public GameObject LoadEnemy(string name)
{
return InstaniateGameObject(EnemyPath + name);
}
public GameObject LoadSoldier(string name)
{
return InstaniateGameObject(SoldierPath + name);
}
public GameObject LoadWeapon(string name)
{
return InstaniateGameObject(WeaponPath + name);
}
public AudioClip LoadAudioClip(string name)
{
return Resources.Load<AudioClip>(AudioPath + name);
}
public Sprite LoadSprites(string name)
{
return Resources.Load<Sprite>(SpritePath+name);
}
/// <summary>
/// 加载需要实例化的物体
/// </summary>
/// <param name="path">加载路径</param>
/// <returns></returns>
private GameObject InstaniateGameObject(string path)
{
Object o = Resources.Load(path);
if (o == null)
{ Debug.LogWarning("无法加载资源,路径:"+path); return null; }
return GameObject.Instantiate(o) as GameObject;
}
}
开发武器工厂 :
创建接口类IWeapon
public interface IWeaponFactory
{
IWeapon CreateWeapon(WeaponType weaponType);
}
对IWeapon写入构造方法:
public abstract class IWeapon
{
protected int mAtk;//最大攻击力
protected float mAtkRange;//最大攻击范围
protected GameObject mGameObject;//武器模型
protected ICharacter mOwner;//武器持有者
protected ParticleSystem mParticle;//武器特效
protected LineRenderer mLineRender;//武器射线
protected Light mLight;
protected AudioSource mAudioSource; //音效
protected float mEffectDisplayTime;//特效显示时间
public float AtkRange { get { return mAtkRange; } }
public IWeapon(int Atk, float AtkRange, GameObject gameObject)
{
mAtk = Atk;
mAtkRange = AtkRange;
mGameObject = gameObject;
//得到武器特效射线灯光音效的组件,在武器的子物体Effect中
Transform effect = mGameObject.transform.Find("Effect");
mParticle = effect.GetComponent<ParticleSystem>();
mLineRender = effect.GetComponent<LineRenderer>();
mLight = effect.GetComponent<Light>();
mAudioSource = effect.GetComponent<AudioSource>();
}
…………省略
Weapon工厂实例化武器:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class WeaponFactory : IWeaponFactory
{
public IWeapon CreateWeapon(WeaponType weaponType)
{
IWeapon weapon = null;
string assetsName = "";
switch (weaponType)
{
case WeaponType.Gun:
assetsName = "WeaponGun";
break;
case WeaponType.Rifle:
assetsName = "WeaponRifle";
break;
case WeaponType.Rocket:
assetsName = "WeaponRocket";
break;
}
GameObject weaponGO= FactoryManager.assetFactory.LoadWeapon(assetsName);
switch (weaponType)
{
case WeaponType.Gun:
weapon = new WeaponGun(20,5,weaponGO);
break;
case WeaponType.Rifle:
weapon = new WeaponRifle(30, 7, weaponGO);
break;
case WeaponType.Rocket:
weapon = new WeaponRocket(40, 8, weaponGO);
break;
}
return weapon;
}
}
对工厂进行统一的管理、方便后期维护 :
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public static class FactoryManager
{
private static IAssetFactory mAssetFactory;
private static IWeaponFactory mWeaponFactory;
private static ICharacterFactory mSoldierFactory;
private static ICharacterFactory mEnemyFactory;
public static IAssetFactory assetFactory
{
get
{
if (mAssetFactory == null)
{
mAssetFactory = new ResourcesAssetFactory();
}
return mAssetFactory;
}
}
public static IWeaponFactory weaponFactory
{
get
{
if (mWeaponFactory == null)
{
mWeaponFactory = new WeaponFactory();
}
return mWeaponFactory;
}
}
public static ICharacterFactory soldierFactory
{
get
{
if (mSoldierFactory == null)
{
mSoldierFactory = new SoldierFactory();
}
return mSoldierFactory;
}
}
public static ICharacterFactory enemyFactory
{
get
{
if (mEnemyFactory == null)
{
mEnemyFactory = new EnemyFactory();
}
return mEnemyFactory;
}
}
}
完善创建战士的工厂方法 :
通过资源工厂加载实例化后,通过Set方法获取ICharacter的mGameobject(代表当前的角色)属性,并在set方法中获取Nav、Ani、AudioSource组件,将实例化的物体设置给ICharacter的mGameobject。
再给角色添加武器 - 通过资源工厂加载实例化后,通过Set方法获取ICharacter的mWeapon属性,并在set方法中 1.将IWeapon中的 protected ICharacter mOwner(武器持有者 ) Set 出来,将其设置给当前的ICharacter,即this 2.找到放置武器的位置并给武器设置父亲
创建工具类脚本UnityTools - FindChild()方法用于 找到放置武器的位置 Attach()方法用于给武器设置父亲
public class SoldierFactory : ICharacterFactory
{
public ICharacter CreateCharacter<T>(WeaponType weaponType, Vector3 spawnPos, int lv = 1) where T : ICharacter, new()
{
ICharacter character = new T();
string mName;
int mMaxHp;
float mMoveSpeed;
string mIconSprite; // 资源加载
string mPrefabName;// 通过Prefab名字实例化Prefab
System.Type type = typeof(T);
if (type == typeof(SoldierCaptain))
{
mName = "上尉士兵";
mMaxHp = 100;
mMoveSpeed = 3;
mIconSprite = "CaptainIcon";
mPrefabName = "Soldier1";
}
else if (type == typeof(SoldierSergeant))
{
mName = "中士士兵";
mMaxHp = 90;
mMoveSpeed = 3;
mIconSprite = "SergeantIcon";
mPrefabName = "Soldier2";
}
else if (type == typeof(SoldierRookie))
{
mName = "新手士兵";
mMaxHp = 80;
mMoveSpeed = 2.5f;
mIconSprite = "RookieIcon";
mPrefabName = "Soldier3";
}
else {
Debug.LogWarning("战士类型["+type+"]不存在");
return null;
}
ICharacterAttr attr = new ICharacterAttr(new SoldierAttrStrategy(),mName,mMaxHp,mMoveSpeed,mIconSprite,mPrefabName);
character.CharacterAttri = attr;
//创建角色游戏物体
//1. 加载 2. 实例化,设置生成位置
GameObject SoldierGo = FactoryManager.assetFactory.LoadSoldier(mPrefabName);
SoldierGo.transform.position = spawnPos;
//将实例化的角色设置给ICharacter,与ICharacter交互
character.gameObject = SoldierGo;
//添加武器
IWeapon weapon = FactoryManager.weaponFactory.CreateWeapon(weaponType);
character.Weapon = weapon;
return character;
}
}
public abstract class ICharacter
{
protected GameObject mGameObject;//游戏角色
protected NavMeshAgent mNavMeshAgent;
protected AudioSource mAudioSource;
protected ICharacterAttr mCharacterAttri;//角色属性
protected Animation mAnimation;//角色动画
protected IWeapon mWeapon;
public IWeapon Weapon
{
set
{
mWeapon = value;
mWeapon.Owner = this;
//找到放置武器的位置
GameObject child = UnityTools.FindChild(mGameObject, "weapon-point");
//给武器设置父亲
UnityTools.Attach(child,mWeapon.gameObject);
}
}
public ICharacterAttr CharacterAttri { set { mCharacterAttri = value; } get { return mCharacterAttri; } }
public float mAtkRange { get { return mWeapon.AtkRange; } } //武器的攻击距离
public GameObject gameObject
{
get { return mGameObject; }
set
{
mGameObject = value;
mNavMeshAgent = mGameObject.GetComponent<NavMeshAgent>();
mAudioSource = mGameObject.GetComponent<AudioSource>();
mAnimation = mGameObject.transform.GetChild(0).GetComponent<Animation>();
}
}
省略…………
public abstract class IWeapon
{
protected int mAtk;//最大攻击力
protected float mAtkRange;//最大攻击范围
//protected int mAtkPlusValue;//暴击
protected GameObject mGameObject;//武器模型
protected ICharacter mOwner;//武器持有者
protected ParticleSystem mParticle;//武器特效
protected LineRenderer mLineRender;//武器射线
protected Light mLight;
protected AudioSource mAudioSource; //音效
protected float mEffectDisplayTime;//特效显示时间
public float AtkRange { get { return mAtkRange; } }
public ICharacter Owner { set { mOwner = value; } }
public GameObject gameObject { get { return mGameObject; } }
public IWeapon(int Atk, float AtkRange, GameObject gameObject)
{
mAtk = Atk;
mAtkRange = AtkRange;
mGameObject = gameObject;
//得到武器特效射线灯光音效的组件,在武器的子物体Effect中
Transform effect = mGameObject.transform.Find("Effect");
mParticle = effect.GetComponent<ParticleSystem>();
mLineRender = effect.GetComponent<LineRenderer>();
mLight = effect.GetComponent<Light>();
mAudioSource = effect.GetComponent<AudioSource>();
}
省略…………
UnityTools工具类:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public static class UnityTools
{
/// <summary>
/// 工具方法 用于从父物体下寻找子物体
/// </summary>
/// <param name="parent">父物体</param>
/// <param name="childName">要寻找的子物体名字</param>
/// <returns></returns>
public static GameObject FindChild(GameObject parent, string childName)
{
Transform[] transforms = parent.GetComponentsInChildren<Transform>();
bool isFinded = false;
Transform child = null;
foreach (Transform item in transforms)
{
if (item.name == childName)
{
if (isFinded)
Debug.LogWarning("在游戏物体" + parent + "下存在不止一个子物体: " + childName);
isFinded = true;
child = item;
}
}
if(isFinded)
return child.gameObject;
return null;
}
/// <summary>
/// 将一个物体固定在另一物体的下面,作为其子物体
/// </summary>
public static void Attach(GameObject parent,GameObject child)
{
child.transform.parent = parent.transform;
child.transform.localPosition = Vector3.zero;
child.transform.localScale = Vector3.one;
child.transform.localEulerAngles = Vector3.zero;
}
}
完善之前需要加载资源的地方 :
IWeapon的DoPlayAudioSources()方法
ICharacter的DoPlayEffect()和DoPlaySound()方法
IWeapon:
protected void DoPlayAudioSources(string str)
{
string clipName = str;
AudioClip clip = FactoryManager.assetFactory.LoadAudioClip(str);
mAudioSource.clip = clip;
mAudioSource.Play();
}
ICharacter:
protected void DoPlayEffect(string effectName)
{
//加载特效
GameObject effectGO = FactoryManager.assetFactory.LoadEffect(effectName);
effectGO.transform.position = GetPosition;
//控制销毁 -- 在特效自身 加一个 类似计时器的脚本进行销毁。
effectGO.AddComponent<DestroyEffect>();
}
protected void DoPlaySound(string clipName)
{
AudioClip clip = FactoryManager.assetFactory.LoadAudioClip(clipName);
mAudioSource.clip = clip;
mAudioSource.Play();
}
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class DestroyEffect : MonoBehaviour
{
private float time = 1;
private void Start()
{
Invoke("DesEffect", time);
}
private void DesEffect()
{
DestroyImmediate(this);
}
}
修改,在ICharacterAttri构造方法中加入int lv(子类也要修改)。
public ICharacterAttr(IAttrStrategy strategy,int lv,string name,int maxHP,float moveSpeed,string iconSprite,string prefabName)
{
mName = name;
mMaxHp = maxHP;
mMoveSpeed = moveSpeed;
mIconSprite = iconSprite;
mPrefabName = prefabName;
mLv = lv;
mStrategy = strategy;
mDmgDescValue = mStrategy.GetCritDmg(mCritRate);
mCurrentHP = mMaxHp + mStrategy.GetExtraHPValue(mLv);
}
然后在SoldierFactory士兵工厂中New ICharacterAttr时也加入lv。
开发创建敌人的工厂方法 :
public class EnemyFactory : ICharacterFactory
{
public ICharacter CreateCharacter<T>(WeaponType weaponType, Vector3 spawnPos, int lv = 1) where T : ICharacter, new()
{
ICharacter character = new T();
string mName;
int mMaxHp;
float mMoveSpeed;
string mIconSprite; // 资源加载
string mPrefabName;// 通过Prefab名字实例化Prefab
System.Type t = typeof(T);
if (t == typeof(EnemyElf))
{
mName = "小精灵";
mMaxHp = 100;
mMoveSpeed = 3;
mIconSprite = "ElfIcon";
mPrefabName = "Enemy1";
}
else if (t == typeof(EnemyOgre))
{
mName = "怪物";
mMaxHp = 120;
mMoveSpeed = 4;
mIconSprite = "OgreIcon";
mPrefabName = "Enemy2";
}
else if (t == typeof(EnemyTroll))
{
mName = "巨魔";
mMaxHp = 200;
mMoveSpeed = 1;
mIconSprite = "TrollIcon";
mPrefabName = "Enemy3";
}
else
{
Debug.LogWarning("类型[" + t + "]不属于Enemy,无法创建");
return null;
}
ICharacterAttr attr = new ICharacterAttr(new SoldierAttrStrategy(), lv, mName, mMaxHp, mMoveSpeed, mIconSprite, mPrefabName);
character.CharacterAttri = attr;
GameObject enemyGO = FactoryManager.assetFactory.LoadEnemy(mPrefabName);
enemyGO.transform.position = spawnPos;
character.gameObject = enemyGO;
IWeapon weapon = FactoryManager.weaponFactory.CreateWeapon(weaponType);
character.Weapon = weapon;
return character;
}
}
(十)建造者模式
相关链接:http://www.cnblogs.com/BeyondAnyTime/archive/2012/07/19/2599980.html
建造者模式:是将一个复杂的对象的构建与它的表示分离,使得同样的构建过程可以创建不同的表示。
建造者模式源码:
public class BuilderDemo : MonoBehaviour
{
private void Start()
{
IBuilder fatBuilder = new FatPersonBuilder();
IBuilder ThinBuilder = new ThinPersonBuilder();
Person person = Director.Construct(fatBuilder);
person.Show();
}
}
class Person
{
List<string> parts = new List<string>();
public void AddPart(string part)
{
parts.Add(part);
}
public void Show()
{
foreach (string str in parts)
{
Debug.Log(str);
}
}
}
class FatPerson : Person { }
class ThinPerson : Person { }
interface IBuilder
{
void AddHead();
void AddBody();
void AddHand();
void AddFeet();
Person GetResult();
}
class FatPersonBuilder : IBuilder
{
private Person person;
public FatPersonBuilder()
{
person = new FatPerson();
}
public void AddBody()
{
person.AddPart("胖人身体");
}
public void AddFeet()
{
person.AddPart("胖人脚");
}
public void AddHand()
{
person.AddPart("胖人手");
}
public void AddHead()
{
person.AddPart("胖人头");
}
public Person GetResult()
{
return person;
}
}
class ThinPersonBuilder : IBuilder
{
private Person person;
public ThinPersonBuilder()
{
person = new ThinPerson();
}
public void AddBody()
{
person.AddPart("瘦人身体");
}
public void AddFeet()
{
person.AddPart("瘦人脚");
}
public void AddHand()
{
person.AddPart("瘦人手");
}
public void AddHead()
{
person.AddPart("瘦人头");
}
public Person GetResult()
{
return person;
}
}
class Director
{
public static Person Construct(IBuilder builder)
{
builder.AddBody();
builder.AddHead();
builder.AddHand();
builder.AddFeet();
return builder.GetResult();
}
}
开发角色建造者的抽象基类 ICharacterBuilder:
public abstract class ICharacterBuilder
{
protected WeaponType mWeaponType;
protected Vector3 mSpawnPos;
protected int mLV;
protected ICharacter mCharacter;//设置给谁
protected System.Type mT;
protected string mPrefabName;
public ICharacterBuilder(ICharacter character, System.Type t,WeaponType weaponType, Vector3 spawnPos, int lv)
{
mCharacter = character;
mT = t ;
mWeaponType = weaponType;
mLV = lv;
mSpawnPos = spawnPos;
}
public abstract void AddCharacterAttr();
public abstract void AddInstGameObject();
public abstract void AddWeapon();
public abstract ICharacter GetResult();
}
开发战士的建造者类 SoldierBuilder:
public class SoldierBuilder : ICharacterBuilder
{
public SoldierBuilder(ICharacter character, Type t, WeaponType weaponType, Vector3 spawnPos, int lv) : base(character, t, weaponType, spawnPos, lv){
}
public override void AddCharacterAttr()
{
string mName ="";
int mMaxHp = 0;
float mMoveSpeed=0;
string mIconSprite = ""; // 资源加载
mPrefabName = "";// 通过Prefab名字实例化Prefab
if (mT == typeof(SoldierCaptain))
{
mName = "上尉士兵";
mMaxHp = 100;
mMoveSpeed = 3;
mIconSprite = "CaptainIcon";
mPrefabName = "Soldier1";
}
else if (mT == typeof(SoldierSergeant))
{
mName = "中士士兵";
mMaxHp = 90;
mMoveSpeed = 3;
mIconSprite = "SergeantIcon";
mPrefabName = "Soldier2";
}
else if (mT == typeof(SoldierRookie))
{
mName = "新手士兵";
mMaxHp = 80;
mMoveSpeed = 2.5f;
mIconSprite = "RookieIcon";
mPrefabName = "Soldier3";
}
else
{
Debug.LogWarning("战士类型[" + mT + "]不存在");
}
ICharacterAttr attr = new ICharacterAttr(new SoldierAttrStrategy(), mLV, mName, mMaxHp, mMoveSpeed, mIconSprite, mPrefabName);
mCharacter.CharacterAttri = attr;
}
public override void AddInstGameObject()
{
//创建角色游戏物体
//1. 加载 2. 实例化,设置生成位置
GameObject SoldierGo = FactoryManager.assetFactory.LoadSoldier(mPrefabName);
SoldierGo.transform.position = mSpawnPos;
//将实例化的角色设置给ICharacter,与ICharacter交互
mCharacter.gameObject = SoldierGo;
}
public override void AddWeapon()
{
//添加武器
IWeapon weapon = FactoryManager.weaponFactory.CreateWeapon(mWeaponType);
mCharacter.Weapon = weapon;
}
public override ICharacter GetResult()
{
return mCharacter;
}
}
开发敌人的建造者类 EnemyBuilder:
public class EnemyrBuilder : ICharacterBuilder
{
public EnemyrBuilder(ICharacter character, Type t, WeaponType weaponType, Vector3 spawnPos, int lv) : base(character, t, weaponType, spawnPos, lv)
{
}
public override void AddCharacterAttr()
{
string mName = "";
int mMaxHp = 0;
float mMoveSpeed = 0;
string mIconSprite = ""; // 资源加载
string mPrefabName = "";// 通过Prefab名字实例化Prefab
if (mT == typeof(EnemyElf))
{
mName = "小精灵";
mMaxHp = 100;
mMoveSpeed = 3;
mIconSprite = "ElfIcon";
mPrefabName = "Enemy1";
}
else if (mT == typeof(EnemyOgre))
{
mName = "怪物";
mMaxHp = 120;
mMoveSpeed = 4;
mIconSprite = "OgreIcon";
mPrefabName = "Enemy2";
}
else if (mT == typeof(EnemyTroll))
{
mName = "巨魔";
mMaxHp = 200;
mMoveSpeed = 1;
mIconSprite = "TrollIcon";
mPrefabName = "Enemy3";
}
else
{
Debug.LogWarning("类型[" + mT + "]不属于Enemy,无法创建");
}
ICharacterAttr attr = new ICharacterAttr(new SoldierAttrStrategy(), mLV, mName, mMaxHp, mMoveSpeed, mIconSprite, mPrefabName);
mCharacter.CharacterAttri = attr;
}
public override void AddInstGameObject()
{
GameObject enemyGO = FactoryManager.assetFactory.LoadEnemy(mPrefabName);
enemyGO.transform.position = mSpawnPos;
mCharacter.gameObject = enemyGO;
}
public override void AddWeapon()
{
IWeapon weapon = FactoryManager.weaponFactory.CreateWeapon(mWeaponType);
mCharacter.Weapon = weapon;
}
public override ICharacter GetResult()
{
return mCharacter;
}
}
创建建造者类的管理者 CharacterBuilderDirector:
public class CharacterBuilderDirector
{
public static ICharacter Construct(ICharacterBuilder mCharacterBuilder)
{
mCharacterBuilder.AddCharacterAttr();
mCharacterBuilder.AddInstGameObject();
mCharacterBuilder.AddWeapon();
return mCharacterBuilder.GetResult();
}
}
修改战士工厂和敌人工厂:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class SoldierFactory : ICharacterFactory
{
public ICharacter CreateCharacter<T>(WeaponType weaponType, Vector3 spawnPos, int lv = 1) where T : ICharacter, new()
{
ICharacter character = new T();
ICharacterBuilder builder = new SoldierBuilder(character,typeof(T),weaponType,spawnPos,lv);
return CharacterBuilderDirector.Construct(builder);
}
}
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class EnemyFactory : ICharacterFactory
{
public ICharacter CreateCharacter<T>(WeaponType weaponType, Vector3 spawnPos, int lv = 1) where T : ICharacter, new()
{
ICharacter character = new T();
ICharacterBuilder builder = new EnemyrBuilder(character, typeof(T), weaponType, spawnPos, lv);
return CharacterBuilderDirector.Construct(builder);
}
}