在角色身上实现武器实体:
1. 在摄像机下添加一把武器(游戏物体),挂载上Weapon脚本。
2. 武器处理器自动查找 所有摄像机下的Weapon,生成List<vp_Weapon> Weapons,代表当前武器集合
3. 将游戏物体挂载上Identifier脚本,并将bank对象(asset文件)拖拽赋值,还有子弹的赋值
4. 将bank对象拖拽给Inventory面板(或在游戏中调用TryGiveItem),然后我们的背包中就有了一个bankInstance,并且在武器处理器中有一把Weapon与它对应
5. 现在的连接关系:
bank对象(asset文件)------ bankInstance(背包中) ----- Weapon(武器处理器中)
6. 如何切换武器
1.直接通过读取键盘输入:
if (vp_Input.GetButtonDown("SetWeapon1")) FPPlayer.SetWeapon.TryStart(1);
if (vp_Input.GetButtonDown("SetWeapon2")) FPPlayer.SetWeapon.TryStart(2);
if (vp_Input.GetButtonDown("SetWeapon3")) FPPlayer.SetWeapon.TryStart(3);
if (vp_Input.GetButtonDown("SetWeapon4")) FPPlayer.SetWeapon.TryStart(4);
2.通过背包中的item实例:
TryWield ( vp_ItemInstance item ) :
1. 遍历武器处理器中的所有武器Weapons的identifier
2. 通过item.Type == identifier.Type,找到对应的Weapon
3. Player.SetWeapon.TryStart(index);
7. 武器切换(背包)的条件
CanStart_SetWeapon():
1. int index = (int)Player.SetWeapon.Argument;
....检查索引
2. 检查武器的Identifier
不为null,其中的item引用也不为null
3. 背包中是否存在这把武器的实例
bool haveItem = HaveItem(Identifier.Type, Identifier.ID);
8. 进入武器处理器
OnStart_SetWeapon():
1.停止当前武器的所有活动,卸下当前武器m_CurrentWeapon.Wield(false);,设置切换武器这个动作的持续时间(0.1s,就是说0.1秒后SetWeapon这个活动直接结束)
OnStop_SetWeapon():
1.index = (int)m_Player.SetWeapon.Argument;
2.SetWeapon(index):
1.DeactivateAll(Weapons) //禁用所有武器
2.ActivateWeapon(index); //激活新的武器
a. m_CurrentWeaponIndex = index; //更新当前武器索引
b. m_CurrentWeapon = Weapons[m_CurrentWeaponIndex -
1]; //更新当前武器引用
c. m_CurrentWeapon.ActivateGameObject(true);
//激活当前武器游戏物体
d. m_CurrentShooter = CurrentWeapon.GetComponent
<vp_Shooter>();//更新当前武器shooter
3. m_CurrentWeapon.Wield();
1. m_Wielded = isWielding;
2. Refresh();
3.StateManager.CombineStates();
9. 总结
1.我们先实现了一把武器的所有功能(开火,后坐力,摇摆,火光,声音等等),生成一个武器游戏物体,放到我们的摄像机下,然后这把武器默认是禁用的,同理,所有武器在开始时都是禁用的,然后通过武器处理器设置不同的武器可用,通过这种方式来进行不同武器的切换(切换当前手持的武器,激活这个武器)
2. 这些武器全部会在武器处理器中的Weapons集合存在,代表我们所有可用的武器库,可以想象成一个物品库,里面是我们所有可以得到的物品,但是不代表我们当前可以使用这些武器,我们还要在背包中存在这把武器,对吧,我们必须将这把武器添加到背包中
1.游戏开始前:拖拽到inventory的面板中
2.游戏中:调用TryGiveItem(weapon.identifier.type))
3. 现在这把武器就在我们的背包中存在了,我们就可以切换到这把武器了,有2种方式
1.键盘输入切换对应的武器,背包遍历背包中的所有bank实例,发现背包中 确实存在这么一个bank实例,开始切换
2.调用背包的TryWield( getItem(weapon.identifier.type)),背包遍历武器处 理器中的所有武器,发现武器处理器中确实有这么一把Weapon,开始切换
vp_PlayerInventory功能重载
1.添加武器实例(重写父类)
DoAddUnitBank( vp_UnitBankType unitBankType):(重写父类)
1. 获取我们背包中是否有这个bank对象的bank实例
2. 用这个bank对象添加一个bank实例到我们的背包中
3. 尝试穿戴新的bank对象(不是实例),调用TryWieldNewItem (vp_ItemType type,
bool alreadyHaveIt) ,然后他会调用TryWield( GetItem(type) ),尝试穿戴这个武器,
因为已经添加到背包了,所以一定是能穿戴成功的
父类功能二次实现:
1.TryGiveItem (vp_ItemType itemType)
2.TryGiveItems
2.尝试穿戴武器
TryWield ( vp_ItemInstance item ) :
1. 遍历武器处理器中的所有武器Weapons的identifier
2. 通过item.Type == identifier.Type,找到对应的Weapon
3. Player.SetWeapon.TryStart(index);
3.移除武器实例(重写父类)
DoRemoveUnitBank(vp_UnitBankInstance bank):
1.尝试卸下这把武器(如果当前正好穿戴着这把武器)
Unwield(bank);
2.移除武器:base.DoRemoveUnitBank(bank);
DoRemoveItem(vp_ItemInstance item)
1.尝试卸下这把武器(如果当前正好穿戴着这把武器)
Unwield(item);
2.移除武器:base.DoRemoveUnitBank(item);
父类功能二次实现:
1. TryRemoveItem (vp_ItemType type, int id)
4.尝试卸下武器:
Unwield(vp_ItemInstance item):
如果需要卸下的是当前正在穿戴着的武器,就卸下它
1. if (item.Type != CurrentWeaponIdentifier.Type) return; //只卸当前武器
2. Player.SetWeapon.Start(0); //设置空手(注意:设置0时背包会跳过检查武器是否存在于背包中)
3. Player.SetNextWeapon.Try(); //角色不应该为空手(注意:因为不是SetWeapon事件,所以这里会让武器处理器自动切换到下一把武器库的武器,而不会检查identifier,或是否存在于背包,这样就可能装上一把不存在背包中的武器,所以就有了下一行)
4. vp_Timer.In(1.0f, UnwieldMissingWeapon); //1秒后检查当前武器的身份
5.检查当前武器身份
UnwieldMissingWeapon():
确认当前穿戴的武器的身份信息:
1. 当前武器是否有Identifier组件
2. 当前武器的Identifier 的item对象是否为 null
3. 当前武器的Identifier 的item对象是否存在于背包中(item实例集合,bank
实例集合)
如果上述条件有一个不满足,那么我们会
1.切换为空手(没有武器,null)
2.打印错误(提示这个武器身上的Identifier 组件错误)
6.设置武器的子弹(重写父类)
1.移除武器的子弹
DoRemoveUnits(vp_UnitBankInstance bank, int amount)
1.移除子弹
base.DoRemoveUnits(bank, amount);
2.如果没子弹了,尝试自动换弹
if (bank.Count == 0)
vp_Timer.In(0.3f, delegate() { Player.AutoReload.Try(); });
2.增加武器子弹
DoAddUnits(vp_UnitBankInstance bank, int amount)
实现了一点新逻辑,如果是给内部银行添加库存,会尝试切换枪,和自动换弹的一些逻辑,不用深究
父类功能二次实现:
1. TryDeduct (vp_UnitBankType unitBankType, int unitBankId, int amount) 消耗一把枪的多少子弹
2. TryGiveUnits (vp_UnitBankInstance bank, int amount)
3. TryReload (vp_UnitBankInstance bank, int amount)
7.武器的子弹数:
//获取武器的子弹数
GetAmmoInWeapon(vp_Weapon weapon):
实现方法:
1.找到identifier,获取bank对象,通过getItem,获取itemInstance,强
转为bankInstance,获取数量
//获取武器子弹的库存数
GetExtraAmmoForWeapon(vp_Weapon weapon)
实现方法:
1. 找到identifier,获取bank对象,获取unit对象,作为参数获取内部银行 的库存量
8.穿戴使用这种子弹的武器
TryWieldByUnit (vp_UnitType unitType):
实现方式:
1.用一个字典保存每个武器对应的identifier(保存武器库里所有的武器和它的identifier,不涉及背包)
2.用一个字典保存每种子弹对应的武器集合(遍历每个武器,找到identifier,获取子弹类型,也是保存武器库里所有的武器和它的子弹类型,不涉及背包)
3.获取这个子弹对应武器库中的所有武器,每一把都尝试穿戴m_Player.SetWeapon
.TryStart(),不在背包中的会穿戴失败,直到有一把背包中的武器穿戴上,返回true,否则返回false
9.当前武器信息
1.当前武器子弹
OnValue_CurrentWeaponAmmoCount:
实现方式:
1.CurrentWeaponIdentifier属性:调用时通过访问武器处理器获取当前使用武
器的identifier
2.CurrentWeaponInstance属性:当前使用武器的在背包中的itemInstance。
通过GetItem(CurrentWeaponIdentifier.Type);
3.返回:((vp_bankInstance)CurrentWeaponInstance).Count
2.当前武器子弹的库存量(内部银行)
OnValue_CurrentWeaponClipCount:
实现方式:
通过当前武器的item实例,转成bank实例,读取unit,作为参数获取内部银行库存量
10. 武器对象 <---> 背包实例 互相转换
武器对象 转 背包实例
vp_UnitBankInstance GetUnitBankInstanceOfWeapon(vp_Weapon weapon):
实现方法:
获取identifier,获取bank,作为参数传入getItem,返回itemInstance,强转为bankInstance返回
背包实例 转 武器对象
vp_Weapon GetWeaponOfItemInstance(vp_ItemInstance itemInstance)
实现方法:
遍历武器库所有武器,找到一把武器满足identifier.Type == itemInstance.Type,返回武器