Skip to content

Commit 418aea6

Browse files
committed
Made projectile loop more efficient
Emitters will now only loop through an array of active indices instead of n number of projectiles
1 parent 487d874 commit 418aea6

6 files changed

Lines changed: 154 additions & 106 deletions

File tree

Assets/Unity-Bullet-Hell/Scenes/LiquidDemo.unity

Lines changed: 11 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -249,11 +249,6 @@ MonoBehaviour:
249249
m_EditorClassIdentifier:
250250
ProjectilePrefab: {fileID: 8841699598713729355, guid: 4fedefd988960d247aaa18371098f2c1,
251251
type: 3}
252-
INTERVAL: 0.1
253-
Direction: {x: -1, y: 0}
254-
TimeToLive: 15
255-
Speed: 1
256-
MaxSpeed: 100
257252
Scale: 0.15
258253
Color:
259254
serializedVersion: 2
@@ -284,13 +279,18 @@ MonoBehaviour:
284279
m_Mode: 0
285280
m_NumColorKeys: 2
286281
m_NumAlphaKeys: 2
287-
RotationSpeed: 0
282+
TimeToLive: 15
283+
CoolOffTime: 0.1
288284
AutoFire: 1
289-
BounceOffSurfaces: 1
290-
CullProjectilesOutsideCameraBounds: 0
285+
Direction: {x: -1, y: 0}
286+
Speed: 1
287+
MaxSpeed: 100
288+
RotationSpeed: 0
291289
CollisionDetection: 1
292-
IsVariableTimeStep: 0
293-
FIXED_TIMESTEP_RATE: 0.02
290+
BounceOffSurfaces: 1
291+
CullProjectilesOutsideCameraBounds: 1
292+
IsFixedTimestep: 1
293+
FixedTimestepRate: 0.01
294294
ProjectilePoolSize: 20000
295295
DrawOutlines: 1
296296
OutlineSize: 0.04
@@ -340,7 +340,7 @@ MonoBehaviour:
340340
Target: {fileID: 0}
341341
FollowTargetType: 0
342342
FollowIntensity: 0
343-
UseOutlineColorPulse: 1
343+
UseOutlineColorPulse: 0
344344
OutlinePulseSpeed: 0.9
345345
UseOutlineStaticPulse: 0
346346
--- !u!4 &86362418

Assets/Unity-Bullet-Hell/Scenes/SampleScene.unity

Lines changed: 41 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -385,7 +385,7 @@ PrefabInstance:
385385
- target: {fileID: 5637193097534451155, guid: d3901bae36dc6884da48a493d489cb35,
386386
type: 3}
387387
propertyPath: m_IsActive
388-
value: 0
388+
value: 1
389389
objectReference: {fileID: 0}
390390
- target: {fileID: 5637193097534451153, guid: d3901bae36dc6884da48a493d489cb35,
391391
type: 3}
@@ -442,6 +442,36 @@ PrefabInstance:
442442
propertyPath: m_LocalEulerAnglesHint.z
443443
value: 0
444444
objectReference: {fileID: 0}
445+
- target: {fileID: 5637193097534451152, guid: d3901bae36dc6884da48a493d489cb35,
446+
type: 3}
447+
propertyPath: SpokeCount
448+
value: 1
449+
objectReference: {fileID: 0}
450+
- target: {fileID: 5637193097534451152, guid: d3901bae36dc6884da48a493d489cb35,
451+
type: 3}
452+
propertyPath: Direction.x
453+
value: -1
454+
objectReference: {fileID: 0}
455+
- target: {fileID: 5637193097534451152, guid: d3901bae36dc6884da48a493d489cb35,
456+
type: 3}
457+
propertyPath: ProjectilePoolSize
458+
value: 10
459+
objectReference: {fileID: 0}
460+
- target: {fileID: 5637193097534451152, guid: d3901bae36dc6884da48a493d489cb35,
461+
type: 3}
462+
propertyPath: CoolOffTime
463+
value: 0.1
464+
objectReference: {fileID: 0}
465+
- target: {fileID: 5637193097534451152, guid: d3901bae36dc6884da48a493d489cb35,
466+
type: 3}
467+
propertyPath: TimeToLive
468+
value: 5
469+
objectReference: {fileID: 0}
470+
- target: {fileID: 5637193097534451152, guid: d3901bae36dc6884da48a493d489cb35,
471+
type: 3}
472+
propertyPath: IsFixedTimestep
473+
value: 1
474+
objectReference: {fileID: 0}
445475
m_RemovedComponents: []
446476
m_SourcePrefab: {fileID: 100100000, guid: d3901bae36dc6884da48a493d489cb35, type: 3}
447477
--- !u!1 &1319106036
@@ -690,6 +720,11 @@ PrefabInstance:
690720
propertyPath: m_Name
691721
value: InverseFlower
692722
objectReference: {fileID: 0}
723+
- target: {fileID: 3453500415576585352, guid: 8ffa35d3cefc3894c8637e5fe90f0cc1,
724+
type: 3}
725+
propertyPath: m_IsActive
726+
value: 1
727+
objectReference: {fileID: 0}
693728
- target: {fileID: 3453500415576585398, guid: 8ffa35d3cefc3894c8637e5fe90f0cc1,
694729
type: 3}
695730
propertyPath: m_LocalPosition.x
@@ -850,5 +885,10 @@ PrefabInstance:
850885
propertyPath: FIXED_TIMESTEP_RATE
851886
value: 0.02
852887
objectReference: {fileID: 0}
888+
- target: {fileID: 3453500415576585399, guid: 8ffa35d3cefc3894c8637e5fe90f0cc1,
889+
type: 3}
890+
propertyPath: ProjectilePoolSize
891+
value: 5000
892+
objectReference: {fileID: 0}
853893
m_RemovedComponents: []
854894
m_SourcePrefab: {fileID: 100100000, guid: 8ffa35d3cefc3894c8637e5fe90f0cc1, type: 3}

Assets/Unity-Bullet-Hell/Scripts/Core/Pool.cs

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ public struct Node
1111
public bool Active;
1212
}
1313

14-
public Node[] Nodes;
14+
private Node[] Nodes;
1515
private Queue<int> Available;
1616

1717
public int ActiveNodes
@@ -74,7 +74,6 @@ public void Return(int index)
7474
Available.Enqueue(Nodes[index].NodeIndex);
7575
}
7676
}
77-
7877
}
7978

8079
}

Assets/Unity-Bullet-Hell/Scripts/Emitters/ProjectileEmitterAdvanced.cs

Lines changed: 40 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ public class ProjectileEmitterAdvanced : ProjectileEmitterBase
1313
ColorPulse StaticOutlinePulse;
1414
ColorPulse StaticPulse;
1515

16-
[Foldout("General", true)]
16+
[Foldout("Appearance", true)]
1717
[SerializeField] public bool UseColorPulse;
1818
[ConditionalField(nameof(UseColorPulse)), SerializeField] protected float PulseSpeed;
1919
[ConditionalField(nameof(UseColorPulse)), SerializeField] protected bool UseStaticPulse;
@@ -45,11 +45,16 @@ public class ProjectileEmitterAdvanced : ProjectileEmitterBase
4545
public new void Awake()
4646
{
4747
base.Awake();
48-
Groups = new EmitterGroup[10];
4948

49+
Groups = new EmitterGroup[10];
5050
RefreshGroups();
5151
}
5252

53+
void Start()
54+
{
55+
// To allow for the enable / disable checkbox in Inspector
56+
}
57+
5358
private void RefreshGroups()
5459
{
5560
if (GroupCount > 10)
@@ -115,7 +120,7 @@ public override Pool<ProjectileData>.Node FireProjectile(Vector2 direction, floa
115120

116121
for (int g = 0; g < GroupCount; g++)
117122
{
118-
if (Projectiles.AvailableCount > SpokeCount)
123+
if (Projectiles.AvailableCount >= SpokeCount)
119124
{
120125
float rotation = 0;
121126
bool left = true;
@@ -178,6 +183,18 @@ public override Pool<ProjectileData>.Node FireProjectile(Vector2 direction, floa
178183
node.Item.Outline = outlineNode;
179184
}
180185

186+
// Keep track of active projectiles
187+
PreviousActiveProjectileIndexes[ActiveProjectileIndexesPosition] = node.NodeIndex;
188+
ActiveProjectileIndexesPosition++;
189+
if (ActiveProjectileIndexesPosition < ActiveProjectileIndexes.Length)
190+
{
191+
PreviousActiveProjectileIndexes[ActiveProjectileIndexesPosition] = -1;
192+
}
193+
else
194+
{
195+
Debug.Log("Error: Projectile was fired before list of active projectiles was refreshed.");
196+
}
197+
181198
left = !left;
182199
}
183200

@@ -186,7 +203,7 @@ public override Pool<ProjectileData>.Node FireProjectile(Vector2 direction, floa
186203
else
187204
Groups[g].Direction = Rotate(Groups[g].Direction, RotationSpeed);
188205
}
189-
}
206+
}
190207

191208
return node;
192209
}
@@ -252,7 +269,6 @@ private float CalculateGroupRotation(int index, float currentRotation)
252269
return currentRotation;
253270
}
254271

255-
// There is code duplication here, instead of calling base update. this prevents from having to loop the projectiles twice.
256272
protected override void UpdateProjectiles(float tick)
257273
{
258274
ActiveProjectileCount = 0;
@@ -265,25 +281,33 @@ protected override void UpdateProjectiles(float tick)
265281
}
266282

267283
UpdateStaticPulses(tick);
268-
ActiveProjectileIndexesPosition = 0;
269284

270-
// loop through all active projectile data
271-
for (int i = 0; i < Projectiles.Nodes.Length; i++)
285+
int previousIndexCount = ActiveProjectileIndexesPosition;
286+
ActiveProjectileIndexesPosition = 0;
287+
288+
// Only loop through currently active projectiles
289+
for (int i = 0; i < PreviousActiveProjectileIndexes.Length - 1; i++)
272290
{
273-
UpdateProjectile(ref Projectiles.Nodes[i], tick);
291+
// End of array is set to -1
292+
if (PreviousActiveProjectileIndexes[i] == -1)
293+
break;
274294

275-
if (Projectiles.Nodes[i].Active)
295+
Pool<ProjectileData>.Node node = Projectiles.GetActive(PreviousActiveProjectileIndexes[i]);
296+
UpdateProjectile(ref node, tick);
297+
298+
// If still active store in our active projectile collection
299+
if (node.Active)
276300
{
277-
ActiveProjectileIndexes[ActiveProjectileIndexesPosition] = Projectiles.Nodes[i].NodeIndex;
301+
ActiveProjectileIndexes[ActiveProjectileIndexesPosition] = node.NodeIndex;
278302
ActiveProjectileIndexesPosition++;
279303
}
280304
}
281305

282-
// Set end point of array if not full
283-
if (ActiveProjectileIndexesPosition + 1 < ActiveProjectileIndexes.Length - 1)
284-
{
285-
ActiveProjectileIndexes[ActiveProjectileIndexesPosition + 1] = -1;
286-
}
306+
// Set end point of array so we know when to stop looping
307+
ActiveProjectileIndexes[ActiveProjectileIndexesPosition] = -1;
308+
309+
// Overwrite old previous active projectile index array
310+
System.Array.Copy(ActiveProjectileIndexes, PreviousActiveProjectileIndexes, Mathf.Max(ActiveProjectileIndexesPosition, previousIndexCount));
287311
}
288312

289313
protected override void UpdateProjectile(ref Pool<ProjectileData>.Node node, float tick)

0 commit comments

Comments
 (0)