diff --git a/DungeonShooting_Godot/src/framework/activity/ActivityObject.cs b/DungeonShooting_Godot/src/framework/activity/ActivityObject.cs index 073adca..6f5f9be 100644 --- a/DungeonShooting_Godot/src/framework/activity/ActivityObject.cs +++ b/DungeonShooting_Godot/src/framework/activity/ActivityObject.cs @@ -791,7 +791,7 @@ for (int i = 0; i < _components.Count; i++) { var temp = _components[i]; - if (temp.Key == type) + if (temp.Key.IsAssignableTo(type)) { return temp.Value; } @@ -802,7 +802,7 @@ for (var i = 0; i < _changeComponents.Count; i++) { var temp = _components[i]; - if (temp.Value.GetType() == type) + if (temp.Value.GetType().IsAssignableTo(type)) { return temp.Value; } @@ -817,9 +817,28 @@ /// public T GetComponent() where T : Component { - var component = GetComponent(typeof(T)); - if (component == null) return null; - return (T)component; + for (int i = 0; i < _components.Count; i++) + { + var temp = _components[i]; + if (temp.Value is T component) + { + return component; + } + } + + if (_updatingComp) + { + for (var i = 0; i < _changeComponents.Count; i++) + { + var temp = _components[i]; + if (temp.Value is T component) + { + return component; + } + } + } + + return null; } /// diff --git a/DungeonShooting_Godot/src/framework/activity/components/MoveController.cs b/DungeonShooting_Godot/src/framework/activity/components/MoveController.cs index 1df0c7d..f193d53 100644 --- a/DungeonShooting_Godot/src/framework/activity/components/MoveController.cs +++ b/DungeonShooting_Godot/src/framework/activity/components/MoveController.cs @@ -369,7 +369,7 @@ { //调用移动碰撞函数 Master.OnMoveCollision(collision); - if (Master.IsDestroyed) + if (Master.IsDestroyed || (Master is IPoolItem poolItem && poolItem.IsRecycled)) { return; } @@ -385,11 +385,15 @@ } var length = _forceList.Count; - var v = newVelocity / (length / Master.ActivityMaterial.BounceStrength); - for (var i = 0; i < _forceList.Count; i++) + if (length != 0) { - _forceList[i].Velocity = v; + var v = newVelocity / (length / Master.ActivityMaterial.BounceStrength); + for (var i = 0; i < _forceList.Count; i++) + { + _forceList[i].Velocity = v; + } } + //调用反弹函数 Master.OnBounce(rotation); } diff --git a/DungeonShooting_Godot/src/framework/pool/ObjectPool.cs b/DungeonShooting_Godot/src/framework/pool/ObjectPool.cs index 27f8e4c..b21242b 100644 --- a/DungeonShooting_Godot/src/framework/pool/ObjectPool.cs +++ b/DungeonShooting_Godot/src/framework/pool/ObjectPool.cs @@ -13,6 +13,10 @@ /// public static void Reclaim(IPoolItem poolItem) { + if (poolItem.IsRecycled) + { + return; + } var logotype = poolItem.Logotype; if (!_pool.TryGetValue(logotype, out var poolItems)) { diff --git a/DungeonShooting_Godot/src/game/activity/bullet/explode/Explode.cs b/DungeonShooting_Godot/src/game/activity/bullet/explode/Explode.cs index 6ac0354..d21bca8 100644 --- a/DungeonShooting_Godot/src/game/activity/bullet/explode/Explode.cs +++ b/DungeonShooting_Godot/src/game/activity/bullet/explode/Explode.cs @@ -109,7 +109,7 @@ public void OnReclaim() { - GetParent().RemoveChild(this); + GetParent().CallDeferred(Node.MethodName.RemoveChild, this); } public void OnLeavePool() diff --git a/DungeonShooting_Godot/src/game/activity/bullet/laser/Laser.cs b/DungeonShooting_Godot/src/game/activity/bullet/laser/Laser.cs index 5b503d4..5a62788 100644 --- a/DungeonShooting_Godot/src/game/activity/bullet/laser/Laser.cs +++ b/DungeonShooting_Godot/src/game/activity/bullet/laser/Laser.cs @@ -1,3 +1,4 @@ +using System; using System.Collections; using System.Collections.Generic; using Godot; @@ -11,6 +12,12 @@ public Sprite2D LineSprite { get; private set; } public RectangleShape2D Shape { get; private set; } + public event Action OnReclaimEvent; + public event Action OnLeavePoolEvent; + + public bool IsRecycled { get; set; } + public string Logotype { get; set; } + public uint AttackLayer { get => CollisionMask; @@ -27,17 +34,8 @@ private List _coroutineList; private float _pixelScale; private float _speed = 2000; - - public override void _Ready() - { - Collision = GetNodeOrNull("CollisionShape2D"); - Collision.Disabled = true; - Shape = Collision.Shape as RectangleShape2D; - LineSprite = GetNodeOrNull("LineSprite"); - _pixelScale = 1f / LineSprite.Texture.GetHeight(); - - AreaEntered += OnArea2dEntered; - } + private Tween _tween; + private bool _init = false; public void InitData(BulletData data, uint attackLayer) { @@ -46,6 +44,19 @@ public void InitData(BulletData data, uint attackLayer, float width) { + if (!_init) + { + Collision = GetNodeOrNull("CollisionShape2D"); + Collision.Disabled = true; + Shape = (RectangleShape2D)Collision.Shape; + LineSprite = GetNodeOrNull("LineSprite"); + _pixelScale = 1f / LineSprite.Texture.GetHeight(); + + AreaEntered += OnArea2dEntered; + + _init = true; + } + BulletData = data; AttackLayer = attackLayer; @@ -68,7 +79,7 @@ Collision.SetDeferred(CollisionShape2D.PropertyName.Disabled, false); Collision.Position = Vector2.Zero; - Shape.Size = Vector2.Zero;; + Shape.Size = Vector2.Zero; LineSprite.Scale = new Vector2(0, width * _pixelScale); //如果子弹会对玩家造成伤害, 则显示成红色 @@ -76,31 +87,36 @@ { LineSprite.Modulate = new Color(2.5f, 0.5f, 0.5f); } + else + { + LineSprite.Modulate = new Color(1.5f, 1.5f, 1.5f); + } //激光飞行时间 var time = distance / _speed; - var tween = CreateTween(); - tween.SetParallel(); - tween.TweenProperty(LineSprite, "scale", new Vector2(distance, width * _pixelScale), time); - tween.TweenProperty(Collision, "position", new Vector2(distance * 0.5f, 0), time); - tween.TweenProperty(Shape, "size", new Vector2(distance, width), time); - tween.Chain(); + _tween = CreateTween(); + _tween.SetParallel(); + _tween.TweenProperty(LineSprite, "scale", new Vector2(distance, width * _pixelScale), time); + _tween.TweenProperty(Collision, "position", new Vector2(distance * 0.5f, 0), time); + _tween.TweenProperty(Shape, "size", new Vector2(distance, width), time); + _tween.Chain(); //持续时间 // tween.TweenInterval(0.2f); // tween.Chain(); - tween.TweenCallback(Callable.From(() => + _tween.TweenCallback(Callable.From(() => { Collision.SetDeferred(CollisionShape2D.PropertyName.Disabled, false); })); - tween.Chain(); - tween.TweenProperty(LineSprite, "scale", new Vector2(distance, 0), 0.3f); - tween.Chain(); - tween.TweenCallback(Callable.From(() => + _tween.Chain(); + _tween.TweenProperty(LineSprite, "scale", new Vector2(distance, 0), 0.3f); + _tween.Chain(); + _tween.TweenCallback(Callable.From(() => { - Destroy(); + _tween = null; + DoReclaim(); })); - tween.Play(); + _tween.Play(); } public override void _Process(double delta) @@ -152,4 +168,33 @@ { ProxyCoroutineHandler.ProxyStopAllCoroutine(ref _coroutineList); } + + public void DoReclaim() + { + ObjectPool.Reclaim(this); + } + + public virtual void OnReclaim() + { + if (OnReclaimEvent != null) + { + OnReclaimEvent(); + } + + if (_tween != null) + { + _tween.Dispose(); + _tween = null; + } + GetParent().CallDeferred(Node.MethodName.RemoveChild, this); + } + + public virtual void OnLeavePool() + { + StopAllCoroutine(); + if (OnLeavePoolEvent != null) + { + OnLeavePoolEvent(); + } + } } diff --git a/DungeonShooting_Godot/src/game/activity/bullet/normal/BoomBullet.cs b/DungeonShooting_Godot/src/game/activity/bullet/normal/BoomBullet.cs index d90a457..ae5d5c9 100644 --- a/DungeonShooting_Godot/src/game/activity/bullet/normal/BoomBullet.cs +++ b/DungeonShooting_Godot/src/game/activity/bullet/normal/BoomBullet.cs @@ -10,19 +10,19 @@ public override void OnLimeOver() { PlayBoom(); - Destroy(); + DoReclaim(); } public override void OnMaxDistance() { PlayBoom(); - Destroy(); + DoReclaim(); } public override void OnCollisionTarget(ActivityObject o) { PlayBoom(); - Destroy(); + DoReclaim(); } public override void OnMoveCollision(KinematicCollision2D lastSlideCollision) diff --git a/DungeonShooting_Godot/src/game/activity/bullet/normal/Bullet.cs b/DungeonShooting_Godot/src/game/activity/bullet/normal/Bullet.cs index 1a6e160..d033acc 100644 --- a/DungeonShooting_Godot/src/game/activity/bullet/normal/Bullet.cs +++ b/DungeonShooting_Godot/src/game/activity/bullet/normal/Bullet.cs @@ -1,4 +1,5 @@ +using System; using System.Collections; using Godot; @@ -8,6 +9,12 @@ [Tool] public partial class Bullet : ActivityObject, IBullet { + public event Action OnReclaimEvent; + public event Action OnLeavePoolEvent; + + public bool IsRecycled { get; set; } + public string Logotype { get; set; } + /// /// 碰撞区域 /// @@ -37,15 +44,22 @@ //当前子弹已经飞行的距离 private float CurrFlyDistance = 0; - - public override void OnInit() - { - BounceLockRotation = false; - CollisionArea.AreaEntered += OnArea2dEntered; - } + + private bool _init = false; public virtual void InitData(BulletData data, uint attackLayer) { + if (!_init) + { + CollisionArea.AreaEntered += OnArea2dEntered; + _init = true; + } + + CurrentBounce = 0; + CurrentPenetration = 0; + CurrFlyDistance = 0; + + BounceLockRotation = false; BulletData = data; AttackLayer = attackLayer; Rotation = data.Rotation; @@ -84,8 +98,8 @@ PutDown(RoomLayerEnum.YSortLayer); //播放子弹移动动画 PlaySpriteAnimation(AnimatorNames.Move); - UpdateFall((float)GetProcessDeltaTime()); //强制更新下坠逻辑处理 + UpdateFall((float)GetProcessDeltaTime()); //过期销毁 if (data.LifeTime > 0) @@ -107,7 +121,7 @@ smoke.GlobalPosition = collision.GetPosition() + new Vector2(0, rotated.Y); smoke.GlobalRotation = collision.GetNormal().Angle(); smoke.AddToActivityRoot(RoomLayerEnum.YSortLayer); - Destroy(); + DoReclaim(); } } @@ -136,7 +150,7 @@ CurrentPenetration++; if (CurrentPenetration > BulletData.Penetration) { - Destroy(); + DoReclaim(); } } } @@ -147,7 +161,7 @@ public virtual void OnMaxDistance() { PlayDisappearEffect(); - Destroy(); + DoReclaim(); } /// @@ -156,7 +170,7 @@ public virtual void OnLimeOver() { PlayDisappearEffect(); - Destroy(); + DoReclaim(); } /// @@ -208,4 +222,33 @@ var activityObject = other.AsActivityObject(); OnCollisionTarget(activityObject); } + + public void DoReclaim() + { + ObjectPool.Reclaim(this); + } + + public virtual void OnReclaim() + { + if (OnReclaimEvent != null) + { + OnReclaimEvent(); + } + if (AffiliationArea != null) + { + AffiliationArea.RemoveItem(this); + } + ShowOutline = false; + GetParent().CallDeferred(Node.MethodName.RemoveChild, this); + } + + public virtual void OnLeavePool() + { + MoveController.ClearForce(); + StopAllCoroutine(); + if (OnLeavePoolEvent != null) + { + OnLeavePoolEvent(); + } + } } \ No newline at end of file diff --git a/DungeonShooting_Godot/src/game/activity/bullet/normal/IBullet.cs b/DungeonShooting_Godot/src/game/activity/bullet/normal/IBullet.cs index 6e74709..a81f718 100644 --- a/DungeonShooting_Godot/src/game/activity/bullet/normal/IBullet.cs +++ b/DungeonShooting_Godot/src/game/activity/bullet/normal/IBullet.cs @@ -1,9 +1,19 @@  +using System; using Config; -public interface IBullet : IDestroy, ICoroutine +public interface IBullet : ICoroutine, IPoolItem { /// + /// 当物体被回收时的事件 + /// + event Action OnReclaimEvent; + /// + /// 离开对象池时的事件 + /// + event Action OnLeavePoolEvent; + + /// /// 攻击的层级 /// uint AttackLayer { get; set; } @@ -15,4 +25,8 @@ /// 初始化子弹数据 /// void InitData(BulletData data, uint attackLayer); + /// + /// 执行子弹回收操作 + /// + void DoReclaim(); } \ No newline at end of file diff --git a/DungeonShooting_Godot/src/game/activity/prop/buff/BuffPropProp0010.cs b/DungeonShooting_Godot/src/game/activity/prop/buff/BuffPropProp0010.cs index 9ec8e03..54e4657 100644 --- a/DungeonShooting_Godot/src/game/activity/prop/buff/BuffPropProp0010.cs +++ b/DungeonShooting_Godot/src/game/activity/prop/buff/BuffPropProp0010.cs @@ -27,7 +27,7 @@ private void CalcBulletCountEvent(Weapon weapon, int originCount, RefValue refValue) { - refValue.Value += originCount; + refValue.Value += originCount * 10; } private void CalcBulletDeviationAngleEvent(Weapon weapon, float originAngle, RefValue refValue) diff --git a/DungeonShooting_Godot/src/game/activity/weapon/Weapon_Bullet.cs b/DungeonShooting_Godot/src/game/activity/weapon/Weapon_Bullet.cs index 28f8ae2..80cedf5 100644 --- a/DungeonShooting_Godot/src/game/activity/weapon/Weapon_Bullet.cs +++ b/DungeonShooting_Godot/src/game/activity/weapon/Weapon_Bullet.cs @@ -101,7 +101,7 @@ data.Rotation = fireRotation + Mathf.DegToRad(deviationAngle); //创建子弹 - var bulletInstance = Create(bullet.Prefab); + var bulletInstance = ObjectManager.GetBullet(bullet.Prefab); bulletInstance.InitData(data, GetAttackLayer()); return bulletInstance; } @@ -136,7 +136,7 @@ data.Rotation = fireRotation + Mathf.DegToRad(deviationAngle); //创建激光 - var laser = ResourceManager.LoadAndInstantiate(bullet.Prefab); + var laser = ObjectManager.GetLaser(bullet.Prefab); laser.AddToActivityRoot(RoomLayerEnum.YSortLayer); laser.InitData(data, GetAttackLayer(), 3); return laser; diff --git a/DungeonShooting_Godot/src/game/manager/ObjectManager.cs b/DungeonShooting_Godot/src/game/manager/ObjectManager.cs index 5338453..84b03f7 100644 --- a/DungeonShooting_Godot/src/game/manager/ObjectManager.cs +++ b/DungeonShooting_Godot/src/game/manager/ObjectManager.cs @@ -12,4 +12,28 @@ return explode; } + + public static Bullet GetBullet(string id) + { + var bullet = ObjectPool.GetItem(id); + if (bullet == null) + { + bullet = ActivityObject.Create(id); + bullet.Logotype = id; + } + + return bullet; + } + + public static Laser GetLaser(string resPath) + { + var bullet = ObjectPool.GetItem(resPath); + if (bullet == null) + { + bullet = ResourceManager.LoadAndInstantiate(resPath); + bullet.Logotype = resPath; + } + + return bullet; + } } \ No newline at end of file