GunMayhem-工厂模式优化枪械创建
原先的设计
在原来的实现方案中,使用了一个空物体WeaponPoolObj挂载了WeaponPool脚本,该脚本中利用Dictionary实现对武器名称和武器GameObject的管理。
问题:
- 每个地图场景都要有WeaponPoolObj这个物体
- Unity中的Dictionary不支持序列化,无法在编辑界面中手动添加武器键值对,要用代码添加
- 想实现Dictionary序列化,必须手动实现SerializableDictionary或第三方插件
优化:使用工厂模式优化枪械的创建
- 创建继承自
ScriptableObject的WeaponFactory,方便在Inspector中编辑
- 在WeaponFactory中实现武器的创建
GetWeapon
- 在角色和敌人的脚本中
Resources.Load<WeaponFactory>,并在需要的时候调用GetWeapon方法获取武器
UML类图

代码实现
PlayerBehavior
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43
| using System.Collections; using System.Collections.Generic; using UnityEngine;
public class PlayerBehave : MonoBehaviour { private WeaponFactory weaponFactory;
void Start() { weaponFactory = Resources.Load<WeaponFactory>("WeaponFactory"); setBaseWeapon(); }
public void setWeapon(string name) { if (transform.Find("weapon") != null) Destroy(transform.Find("weapon").gameObject);
GameObject temp = weaponFactory.GetWeapon(name); temp.transform.SetParent(transform); temp.transform.position = weaponPoint.position; temp.transform.localScale = Vector3.one; temp.name = "weapon";
if (transform.Find("weapon") != null) transform.Find("weapon").GetComponent<weapon>().setTeam(playerInfo.getTeam()); else Debug.Log(gameObject.name + " Weapon not found!"); }
public void setBaseWeapon() { setWeapon(firstWeapon); } }
|
WeaponFactory
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93
| using System.Collections; using System.Collections.Generic; using UnityEngine;
[CreateAssetMenu(fileName = "WeaponFactory", menuName = "Factory/WeaponFactory")] public class WeaponFactory : ScriptableObject { #region pistol [SerializeField] private GameObject bull; [SerializeField] private GameObject glock; [SerializeField] private GameObject gold; [SerializeField] private GameObject m1911; #endregion
#region rifle [SerializeField] private GameObject ak47; [SerializeField] private GameObject bizon; [SerializeField] private GameObject m12; [SerializeField] private GameObject p90; #endregion
#region shotGun [SerializeField] private GameObject ithaca; [SerializeField] private GameObject ksg; [SerializeField] private GameObject leaver; [SerializeField] private GameObject sawnOff; #endregion
#region sniper [SerializeField] private GameObject sniper501; [SerializeField] private GameObject awn; [SerializeField] private GameObject hk; [SerializeField] private GameObject m95; #endregion
public GameObject GetWeapon(string GameObjectName) { switch (GameObjectName) { case "bull": return Instantiate(bull); case "glock": return Instantiate(glock); case "gold": return Instantiate(gold); case "m1911": return Instantiate(m1911); case "ak47": return Instantiate(ak47); case "bizon": return Instantiate(bizon); case "m12": return Instantiate(m12); case "p90": return Instantiate(p90); case "ithaca": return Instantiate(ithaca); case "ksg": return Instantiate(ksg); case "leaver": return Instantiate(leaver); case "sawnOff": return Instantiate(sawnOff); case "501": return Instantiate(sniper501); case "awn": return Instantiate(awn); case "hk": return Instantiate(hk); case "m95": return Instantiate(m95); default: Debug.LogWarning("GameObject:" + GameObjectName + "Not Found"); return Instantiate(bull); } } }
|
可优化的地方
GetWeapon采用字符串作为参数来判断生成哪种武器,编码中输入字符串时容易出错,可以改用枚举