在Resources——Picture文件夹中新建Battle——Player文件夹。
将Player的子弹图片资源放到Player文件夹内。这里的子弹命名非常简单,直接是数字,每个数字对应一种飞机ID。
0号子弹的Pixels Per Unit :1000
1号子弹的Pixels Per Unit :600
2号子弹的Pixels Per Unit :300
3号子弹的Pixels Per Unit :500
创建一个Prefab,命名为Bullet,在其中挂载SpriteRenderer组件。将其放在Resources——Prefab——Game文件夹内。
准备 在Player的Prefab中新建一个子节点,命名为“BulletRoot”,并调整一下它的位置,放在飞机头部,注意千万不要修改子节点的Z坐标(保持是0即可),否则它发出的子弹不会和其他飞机碰撞。
Pathes 1 2 3 4 public const string PREFAB_BULLET = PREFAB_GAME_FOLDER + "Bullet" ;public const string BULLET_PICTURE_FOLDER = "Picture/Battle/" ;public const string PLAYER_BULLET_FOLDER = BULLET_PICTURE_FOLDER + "Player/" ;
GameConfig 在GameConfig.json文件中指明子弹速度
Consts 在其中定义基础攻速的常量值。还有攻击的持续之间和CD时间。
1 2 3 4 5 6 7 8 9 10 11 12 public const float FIRE_BASE_TIME = 10f ;public const float FIRE_CD_TIME = 1f ;public const float FIRE_DURATION = 1f ;
我们已经在InitPlane.json文件中配置了每个飞机在各个阶段当中的攻速,这里的计算公式是:
FIRE_BASE_TIME / 配置中定义的攻速值
BulletMgr 在Logic文件夹中新建Bullet文件夹,并在其中新建BulletMgr
,每个场景中需要发射子弹的飞机都会动态挂载这个脚本。它挂载在飞机的子节点“BulletRoot”上
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 using System.Collections;using System.Collections.Generic;using UnityEngine;public class BulletMgr : MonoBehaviour { void Start () { CoroutineMgr.Instance.ExecuteOnce(Fire()); } private IEnumerator Fire () { float time = GetFireTime(); while (true ) { yield return new WaitForSeconds (time ) ; SpawnBullet(); } } private float GetFireTime () { string key = KeysUtil.GetPropertyItemKey(PropertyItem.ItemKey.value , PlaneProperty.Property.fireRate.ToString()); var ratio = DataMgr.Instance.Get<int >(key); return Consts.FIRE_BASE_TIME / (float )ratio; } private void SpawnBullet () { var bulletGo = PoolMgr.Instance.Spawn(Pathes.PREFAB_BULLET); var bullet = bulletGo.AddOrGet<Bullet>(); bullet.SetPos(transform); } }
为了实现通用性,这个脚本之后要重构
修改PlayerView 让PlayerView
挂载BulletMgr
脚本
1 2 3 4 5 private void InitComponent (){ transform.AddCo<BulletMgr>("BulletRoot" ); }
修改PoolConfig 子弹需要对象池管理,在PoolConfig
中写明子弹对象池的配置
1 2 3 4 5 6 7 8 9 10 11 12 public class PoolConfig { public List<PoolData> PoolDatas = new List<PoolData>() { new PoolData { Path = Pathes.PREFAB_BULLET, PreloadCount = 15 , AutoDestroy = false , } }; }
修改ExtendUtil 在其中添加GetOrAdd组件的拓展方法,因为对象池中的对象可能已经挂载了某些组件:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 public static T AddOrGet <T >(this Transform target ) where T : Component{ if (!target.TryGetComponent(out T t)) { t = target.AddCo<T>(); } return t; } public static T AddOrGet <T >(this GameObject target ) where T : Component{ if (!target.TryGetComponent(out T t)) { t = target.AddComponent<T>(); } return t; }
Bullet 每个子弹Prefab都会动态挂载的脚本。在Logic——Bullet文件夹中新建Bullet
脚本
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 using UnityEngine;public class Bullet : MonoBehaviour , IUpdate { private float _speed; private MoveComponent _moveCo; private void Start () { int id = GameStateModel.Instance.SelectedPlaneId; Sprite sprite = LoadMgr.Instance.Load<Sprite>(Pathes.PLAYER_BULLET_FOLDER + id); GetComponent<SpriteRenderer>().sprite = sprite; var reader = ReaderMgr.Instance.GetReader(Pathes.GAME_CONFIG); reader["bulletSpeed" ].Get<float >(value => { _speed = value ; _moveCo = transform.AddCo<MoveComponent>(); _moveCo.Init(_speed); }); } private void OnEnable () { LifeCycleMgr.Instance.Add(LifeName.UPDATE, this ); } public void UpdateFun () { if (_moveCo != null ) { _moveCo.Move(Vector2.up); } } private void OnDisable () { LifeCycleMgr.Instance.Remove(LifeName.UPDATE, this ); } public void SetPos (Transform parent ) { transform.position = parent.position; } private void OnBecameInvisible () { PoolMgr.Instance.Despawn(gameObject); } }
对象池生成的对象默认放在场景中的PoolMgr——BulletPool
对象下
为了实现通用性,这个脚本之后要重构