Created
March 19, 2020 20:52
-
-
Save mandarinx/57b82f2556ea492ff681206bf27cff5f to your computer and use it in GitHub Desktop.
Bullet system
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
//#define LOG_BULLETS | |
//#define OUTOFBOUNDS | |
using System; | |
using System.Collections; | |
using System.Collections.Generic; | |
using System.Diagnostics; | |
using TerrorSquid.Configs; | |
using UnityEngine; | |
using UnityEngine.Rendering; | |
using UnityEngine.SceneManagement; | |
using Debug = UnityEngine.Debug; | |
namespace TerrorSquid.BulletSystem { | |
public enum BulletPatternType { | |
Linear = 0, | |
Wave = 1, | |
SplitDouble = 2, | |
Diamond = 3, | |
Flower = 4, | |
Turret = 5, | |
MultiShot = 6, | |
Circle = 7, | |
Freeze = 8, | |
Jellyfish = 9, | |
Worm = 10, | |
} | |
public struct BulletInstance { | |
public int instanceId; | |
public int index; | |
} | |
public static class Bullets { | |
private static Transform[] tParent; | |
private static Transform[] tBody; | |
private static MeshFilter[] tBodyMesh; | |
private static MeshRenderer[] tBodyRenderer; | |
private static TrailRenderer[] trail; | |
private static Quaternion[] rotLocalSphere; | |
private static Quaternion[] rotBody; | |
private static Quaternion[] rotParent; | |
private static Vector3[] posParent; | |
// private static float[] grace; | |
private static bool[] hidden; | |
private static int[] instanceIds; | |
private static int[] explosionHash; | |
private static int[] despawnInstanceIds; | |
private static int[] patternOffset; | |
private static int[] patternLength; | |
private static int numHots; | |
private static int currentDespawn; | |
private static BulletSystemConfig bSysConfig; | |
private static PlanetAttributes planetAttribs; | |
private static int sequenceLength; | |
private static readonly Dictionary<int, PatternConfig> sequenceConfigs = new Dictionary<int, PatternConfig>(); | |
private static readonly Dictionary<BulletPatternType, PatternConfig> typeConfigs = new Dictionary<BulletPatternType, PatternConfig>(); | |
private static readonly Dictionary<int, int> instanceIdMap = new Dictionary<int, int>(); | |
private static readonly Dictionary<BulletPatternType, int> current = new Dictionary<BulletPatternType, int>(); | |
public static Vector3[] HotPositions { get; private set; } | |
public static Quaternion[] HotRotLocalSpheres { get; private set; } | |
public static int[] HotInstanceIds { get; private set; } | |
public static int NumHotBullets => numHots; | |
private static Action<PatternConfig, Config> VoidInit => (patternconfig, config) => {}; | |
private static Action<PatternConfig, Quaternion, Vector2, float> VoidSpawn => (patternconfig, quaternion, vector2, dt) => {}; | |
private static Action<int, int> VoidDespawn => (a, b) => {}; | |
private static Action VoidDespawnAll => () => {}; | |
private static readonly Dictionary<BulletPatternType, Action<PatternConfig, Config>> cbInit = new Dictionary<BulletPatternType, Action<PatternConfig, Config>> { | |
{ BulletPatternType.Linear, PatternLinear.Init }, | |
{ BulletPatternType.Wave, PatternWave.Init }, | |
{ BulletPatternType.SplitDouble, PatternSplitDouble.Init }, | |
{ BulletPatternType.Diamond, VoidInit }, | |
{ BulletPatternType.Flower, PatternFlower.Init }, | |
{ BulletPatternType.Turret, PatternTurret.Init }, | |
{ BulletPatternType.MultiShot, PatternMultiShot.Init }, | |
{ BulletPatternType.Circle, PatternCircle.Init }, | |
{ BulletPatternType.Freeze, PatternFreeze.Init }, | |
{ BulletPatternType.Jellyfish, PatternJellyfish.Init }, | |
{ BulletPatternType.Worm, PatternWorm.Init }, | |
}; | |
private static readonly Dictionary<BulletPatternType, Action<PatternConfig, Quaternion, Vector2, float>> cbSpawn = new Dictionary<BulletPatternType, Action<PatternConfig, Quaternion, Vector2, float>> { | |
{ BulletPatternType.Linear, PatternLinear.Spawn }, | |
{ BulletPatternType.Wave, PatternWave.Spawn }, | |
{ BulletPatternType.SplitDouble, PatternSplitDouble.Spawn }, | |
{ BulletPatternType.Diamond, VoidSpawn }, | |
{ BulletPatternType.Flower, PatternFlower.Spawn }, | |
{ BulletPatternType.Turret, PatternTurret.Spawn }, | |
{ BulletPatternType.MultiShot, PatternMultiShot.Spawn }, | |
{ BulletPatternType.Circle, PatternCircle.Spawn }, | |
{ BulletPatternType.Freeze, PatternFreeze.Spawn }, | |
{ BulletPatternType.Jellyfish, PatternJellyfish.Spawn }, | |
{ BulletPatternType.Worm, PatternWorm.Spawn }, | |
}; | |
private static readonly Dictionary<BulletPatternType, Action<int, int>> cbDespawn = new Dictionary<BulletPatternType, Action<int, int>> { | |
{ BulletPatternType.Linear, PatternLinear.Despawn}, | |
{ BulletPatternType.Wave, PatternWave.Despawn }, | |
{ BulletPatternType.SplitDouble, PatternSplitDouble.Despawn }, | |
{ BulletPatternType.Diamond, VoidDespawn }, | |
{ BulletPatternType.Flower, PatternFlower.Despawn }, | |
{ BulletPatternType.Turret, PatternTurret.Despawn }, | |
{ BulletPatternType.MultiShot, PatternMultiShot.Despawn }, | |
{ BulletPatternType.Circle, PatternCircle.Despawn }, | |
{ BulletPatternType.Freeze, PatternFreeze.Despawn }, | |
{ BulletPatternType.Jellyfish, PatternJellyfish.Despawn }, | |
{ BulletPatternType.Worm, PatternWorm.Despawn }, | |
}; | |
private static readonly Dictionary<BulletPatternType, Action> cbDespawnAll = new Dictionary<BulletPatternType, Action> { | |
{ BulletPatternType.Linear, PatternLinear.DespawnAll}, | |
{ BulletPatternType.Wave, PatternWave.DespawnAll }, | |
{ BulletPatternType.SplitDouble, PatternSplitDouble.DespawnAll }, | |
{ BulletPatternType.Diamond, VoidDespawnAll }, | |
{ BulletPatternType.Flower, PatternFlower.DespawnAll }, | |
{ BulletPatternType.Turret, PatternTurret.DespawnAll }, | |
{ BulletPatternType.MultiShot, PatternMultiShot.DespawnAll }, | |
{ BulletPatternType.Circle, PatternCircle.DespawnAll }, | |
{ BulletPatternType.Freeze, PatternFreeze.DespawnAll }, | |
{ BulletPatternType.Jellyfish, PatternJellyfish.DespawnAll }, | |
{ BulletPatternType.Worm, PatternWorm.DespawnAll }, | |
}; | |
public static void Init(BulletSystemConfig bulletsConfig, PlanetAttributes planetAttributes) { | |
#if UNITY_EDITOR | |
List<string> sequenceErrors = new List<string>(); | |
if (!BulletPatternSequence.IsValid(bulletsConfig.Sequence, sequenceErrors)) { | |
foreach (string error in sequenceErrors) { | |
Debug.LogError(error); | |
} | |
} | |
#endif | |
bSysConfig = bulletsConfig; | |
planetAttribs = planetAttributes; | |
sequenceLength = bulletsConfig.Sequence.Count; | |
int totalInstances = 0; | |
for (int i = 0; i < sequenceLength; ++i) { | |
totalInstances += bulletsConfig.Sequence.Get(i).MaxNum; | |
} | |
int totalPatternTypes = Enum.GetValues(typeof(BulletPatternType)).Length; | |
tParent = new Transform[totalInstances]; | |
tBody = new Transform[totalInstances]; | |
tBodyMesh = new MeshFilter[totalInstances]; | |
tBodyRenderer = new MeshRenderer[totalInstances]; | |
trail = new TrailRenderer[totalInstances]; | |
rotLocalSphere = new Quaternion[totalInstances]; | |
rotBody = new Quaternion[totalInstances]; | |
rotParent = new Quaternion[totalInstances]; | |
posParent = new Vector3[totalInstances]; | |
// grace = new float[totalInstances]; | |
hidden = new bool[totalInstances]; | |
instanceIds = new int[totalInstances]; | |
explosionHash = new int[totalInstances]; | |
despawnInstanceIds = new int[totalInstances]; | |
HotPositions = new Vector3[totalInstances]; | |
HotRotLocalSpheres = new Quaternion[totalInstances]; | |
HotInstanceIds = new int[totalInstances]; | |
patternOffset = new int[totalPatternTypes]; | |
patternLength = new int[totalPatternTypes]; | |
// calculate lengths | |
for (int i = 0; i < sequenceLength; ++i) { | |
PatternConfig cfg = bulletsConfig.Sequence.Get(i); | |
patternLength[(int)cfg.Type] += cfg.MaxNum; | |
} | |
int patternStart = 0; | |
for (int i = 0; i < totalPatternTypes; ++i) { | |
BulletPatternType type = (BulletPatternType) i; | |
patternOffset[(int)type] = patternStart; | |
patternStart += patternLength[(int)type]; | |
current[type] = 0; | |
} | |
for (int i = 0; i < sequenceLength; ++i) { | |
PatternConfig cfg = bulletsConfig.Sequence.Get(i); | |
int nameHash = cfg.NameHash; | |
sequenceConfigs[nameHash] = cfg; | |
typeConfigs[cfg.Type] = cfg; | |
} | |
} | |
public static void Spawn(PatternConfig config, Quaternion rot, Vector2 dir, float dt) { | |
if (current[config.Type] >= config.MaxNum) { | |
return; | |
} | |
cbSpawn[config.Type].Invoke(config, rot, dir, dt); | |
} | |
public static BulletInstance GetInstance(int nameHash, Quaternion rotLocSphere, Vector2 dir) { | |
PatternConfig cfg = sequenceConfigs[nameHash]; | |
BulletPatternType type = cfg.Type; | |
int cur = current[type]; | |
if (cur >= cfg.MaxNum) { | |
return new BulletInstance { | |
instanceId = -1, | |
index = -1 | |
}; | |
} | |
int i = patternOffset[(int)type] + cur; | |
explosionHash[i] = cfg.ExplosionHash; | |
// grace[i] = 0f; | |
hidden[i] = false; | |
rotLocalSphere[i] = rotLocSphere; | |
rotParent[i] = SphereTools.GetRotation(rotLocSphere); | |
posParent[i] = SphereTools.GetPosition(rotLocSphere, planetAttribs.Center, planetAttribs.Radius); | |
rotBody[i] = SphereTools.GetRotationAroundUp(dir); | |
tParent[i].gameObject.SetActive(true); | |
current[type] += 1; | |
return new BulletInstance { | |
instanceId = instanceIds[i], | |
index = i | |
}; | |
} | |
public static void Hide(int index) { | |
tBodyRenderer[index].enabled = false; | |
trail[index].enabled = false; | |
hidden[index] = true; | |
} | |
public static void Show(int index) { | |
tBodyRenderer[index].enabled = true; | |
trail[index].enabled = true; | |
hidden[index] = false; | |
} | |
public static void Decorate(int index, BulletDecorator decorator) { | |
trail[index].sharedMaterial = decorator.TrailMaterial; | |
trail[index].widthCurve = decorator.TrailWidth; | |
trail[index].time = decorator.TrailTime; | |
tBodyMesh[index].sharedMesh = decorator.BodyMesh; | |
tBodyRenderer[index].sharedMaterial = decorator.BodyMaterial; | |
} | |
public static Quaternion GetSpawnPos(Quaternion playerLocalSphereRotation, Vector2 direction) { | |
return SphereTools.GetLocalSphereRotation(playerLocalSphereRotation, | |
direction, | |
bSysConfig.DegreesSpawnOffset); | |
} | |
public static int GetNextPattern(int currentPattern, BulletPatternSequence sequence) { | |
int search = 1; | |
while (search <= sequenceLength) { | |
int i = (currentPattern + search) % sequenceLength; | |
if (sequence.Get(i).IsRitual) { | |
return i; | |
} | |
++search; | |
} | |
return currentPattern; | |
} | |
public static PatternConfig GetConfig(int nameHash) { | |
return sequenceConfigs[nameHash]; | |
} | |
public static int GetExplosionHash(int instanceId) { | |
return explosionHash[instanceIdMap[instanceId]]; | |
} | |
public static int GetInstanceIndexById(int instanceId) { | |
return instanceIdMap[instanceId]; | |
} | |
public static Transform GetBodyByIndex(int instanceIndex) { | |
return tBody[instanceIndex]; | |
} | |
public static void Despawn(int instanceId) { | |
despawnInstanceIds[currentDespawn] = instanceId; | |
++currentDespawn; | |
} | |
public static void DespawnDeads() { | |
for (int i = 0; i < currentDespawn; ++i) { | |
int despawnInstanceIndex = instanceIdMap[despawnInstanceIds[i]]; | |
BulletPatternType type = GetTypeFromIndex(despawnInstanceIndex); | |
int cur = current[type]; | |
int last = cur - 1; | |
int offset = patternOffset[(int)type]; | |
if (despawnInstanceIndex - offset >= cur) { | |
continue; | |
} | |
trail[despawnInstanceIndex].Clear(); | |
tParent[despawnInstanceIndex].gameObject.SetActive(false); | |
current[type] -= 1; | |
// #if OUTOFBOUNDS | |
// if (last < 0 || last >= CONST.NUM_BULLETS) { | |
// Throw($"DespawnDeads | FROM out of bounds | from: {last} " + | |
// $"instanceId: {despawnInstanceIds[i]}" + | |
// $"despawnIndex: {despawnInstanceIndex}" + | |
// $"offset: {offset}" + | |
// $"pattern type: {type}"); | |
// } | |
// if (despawnInstanceIndex - offset < 0 || despawnInstanceIndex - offset >= CONST.NUM_BULLETS) { | |
// Throw($"DespawnDeads | TO out of bounds | to: {despawnInstanceIndex - offset} " + | |
// $"instanceId: {despawnInstanceIds[i]}" + | |
// $"despawnIndex: {despawnInstanceIndex}" + | |
// $"offset: {offset}" + | |
// $"pattern type: {type}"); | |
// } | |
// #endif | |
cbDespawn[type].Invoke(last, despawnInstanceIndex - offset); | |
// Temporarily store the despawned data | |
TrailRenderer dTrail = trail[despawnInstanceIndex]; | |
Transform dParent = tParent[despawnInstanceIndex]; | |
Transform dBody = tBody[despawnInstanceIndex]; | |
MeshFilter dBodyMesh = tBodyMesh[despawnInstanceIndex]; | |
MeshRenderer dBodyRenderer = tBodyRenderer[despawnInstanceIndex]; | |
Quaternion dRotLocalSphere = rotLocalSphere[despawnInstanceIndex]; | |
Quaternion dRotBody = rotBody[despawnInstanceIndex]; | |
Quaternion dRotParent = rotParent[despawnInstanceIndex]; | |
Vector3 dPosParent = posParent[despawnInstanceIndex]; | |
// float dGrace = grace[despawnInstanceIndex]; | |
bool dHidden = hidden[despawnInstanceIndex]; | |
int dInstanceId = instanceIds[despawnInstanceIndex]; | |
int dExplHash = explosionHash[despawnInstanceIndex]; | |
last += offset; | |
// Move data at the last spot to the despawned slot | |
trail[despawnInstanceIndex] = trail[last]; | |
tParent[despawnInstanceIndex] = tParent[last]; | |
tBody[despawnInstanceIndex] = tBody[last]; | |
tBodyMesh[despawnInstanceIndex] = tBodyMesh[last]; | |
tBodyRenderer[despawnInstanceIndex] = tBodyRenderer[last]; | |
rotLocalSphere[despawnInstanceIndex] = rotLocalSphere[last]; | |
rotBody[despawnInstanceIndex] = rotBody[last]; | |
rotParent[despawnInstanceIndex] = rotParent[last]; | |
posParent[despawnInstanceIndex] = posParent[last]; | |
// grace[despawnInstanceIndex] = grace[last]; | |
hidden[despawnInstanceIndex] = hidden[last]; | |
explosionHash[despawnInstanceIndex] = explosionHash[last]; | |
instanceIds[despawnInstanceIndex] = instanceIds[last]; | |
instanceIdMap[instanceIds[last]] = despawnInstanceIndex; | |
// Assign the despawned data to the last slot | |
trail[last] = dTrail; | |
tParent[last] = dParent; | |
tBody[last] = dBody; | |
tBodyMesh[last] = dBodyMesh; | |
tBodyRenderer[last] = dBodyRenderer; | |
rotLocalSphere[last] = dRotLocalSphere; | |
rotBody[last] = dRotBody; | |
rotParent[last] = dRotParent; | |
posParent[last] = dPosParent; | |
// grace[last] = dGrace; | |
hidden[last] = dHidden; | |
explosionHash[last] = dExplHash; | |
instanceIds[last] = dInstanceId; | |
instanceIdMap[dInstanceId] = last; | |
// Log($"InstanceId (despawned: {dInstanceId} > {last}) (last: {lastId} => {newLastId})"); | |
} | |
currentDespawn = 0; | |
} | |
private static BulletPatternType GetTypeFromIndex(int index) { | |
int n = 0; | |
for (int i = 0; i < patternOffset.Length; ++i) { | |
if (index >= patternOffset[i]) { | |
n = i; | |
continue; | |
} | |
break; | |
} | |
return (BulletPatternType)n; | |
} | |
public static void DespawnAll() { | |
for (int i = 0; i < patternOffset.Length; ++i) { | |
int offset = patternOffset[i]; | |
BulletPatternType type = (BulletPatternType) i; | |
int len = current[type]; | |
for (int j = offset; j < offset + len; ++j) { | |
trail[j].Clear(); | |
tParent[j].gameObject.SetActive(false); | |
} | |
cbDespawnAll[type].Invoke(); | |
current[type] = 0; | |
} | |
currentDespawn = 0; | |
} | |
public static void Update(float dt, Quaternion playerRot, Vector2 playerDirection) { | |
// UpdateGrace(BulletPatternType.Linear, dt); | |
// UpdateGrace(BulletPatternType.Wave, dt); | |
// UpdateGrace(BulletPatternType.SplitDouble, dt); | |
// UpdateGrace(BulletPatternType.Diamond, dt); | |
// UpdateGrace(BulletPatternType.Flower, dt); | |
// UpdateGrace(BulletPatternType.Turret, dt); | |
// UpdateGrace(BulletPatternType.MultiShot, dt); | |
// UpdateGrace(BulletPatternType.Circle, dt); | |
// UpdateGrace(BulletPatternType.Freeze, dt); | |
PatternLinear.Update(dt, patternOffset[(int)BulletPatternType.Linear], rotLocalSphere, rotBody, playerRot, playerDirection); | |
PatternWave.Update(dt, patternOffset[(int)BulletPatternType.Wave], rotLocalSphere, rotBody, playerRot, playerDirection); | |
PatternSplitDouble.Update(dt, patternOffset[(int)BulletPatternType.SplitDouble], rotLocalSphere, rotBody, playerRot, playerDirection); | |
// PatternDiamond.Update(dt, patternOffset[(int)BulletPatternType.Diamond], rotLocalSphere, rotBody, playerRot, playerDirection); | |
PatternFlower.Update(dt, patternOffset[(int)BulletPatternType.Flower], rotLocalSphere, rotBody, playerRot, playerDirection); | |
PatternTurret.Update(dt, patternOffset[(int)BulletPatternType.Turret], rotLocalSphere, rotBody, playerRot, playerDirection); | |
PatternMultiShot.Update(dt, patternOffset[(int)BulletPatternType.MultiShot], rotLocalSphere, rotBody, playerRot, playerDirection); | |
PatternCircle.Update(dt, patternOffset[(int)BulletPatternType.Circle], rotLocalSphere, rotBody, playerRot, playerDirection); | |
PatternFreeze.Update(dt, patternOffset[(int)BulletPatternType.Freeze], rotLocalSphere, rotBody, playerRot, playerDirection); | |
PatternJellyfish.Update(dt, patternOffset[(int)BulletPatternType.Jellyfish], rotLocalSphere, rotBody, playerRot, playerDirection); | |
PatternWorm.Update(dt, patternOffset[(int)BulletPatternType.Worm], rotLocalSphere, rotBody, playerRot, playerDirection); | |
WriteTransforms(BulletPatternType.Linear); | |
WriteTransforms(BulletPatternType.Wave); | |
WriteTransforms(BulletPatternType.SplitDouble); | |
// WriteTransforms(BulletPatternType.Diamond); | |
WriteTransforms(BulletPatternType.Flower); | |
WriteTransforms(BulletPatternType.Turret); | |
WriteTransforms(BulletPatternType.MultiShot); | |
WriteTransforms(BulletPatternType.Circle); | |
WriteTransforms(BulletPatternType.Freeze); | |
WriteTransforms(BulletPatternType.Jellyfish); | |
WriteTransforms(BulletPatternType.Worm); | |
} | |
public static void CacheHotBullets() { | |
numHots = 0; | |
for (int i = 0; i < patternOffset.Length; ++i) { | |
int offset = patternOffset[i]; | |
BulletPatternType type = (BulletPatternType)i; | |
int len = current[type]; | |
for (int j = offset; j < offset + len; ++j) { | |
// if (grace[j] < bSysConfig.GracePeriodAtSpawn) { | |
// continue; | |
// } | |
if (hidden[j]) { | |
continue; | |
} | |
HotPositions[numHots] = posParent[j]; | |
HotRotLocalSpheres[numHots] = rotLocalSphere[j]; | |
HotInstanceIds[numHots] = instanceIds[j]; | |
++numHots; | |
} | |
} | |
} | |
// private static void UpdateGrace(BulletPatternType type, float dt) { | |
// int from = patternOffset[(int)type]; | |
// int to = from + current[type]; | |
// for (int i = from; i < to; ++i) { | |
// grace[i] += dt; | |
// } | |
// } | |
private static void WriteTransforms(BulletPatternType type) { | |
int from = patternOffset[(int)type]; | |
int to = from + current[type]; | |
for (int i = from; i < to; ++i) { | |
rotParent[i] = SphereTools.GetRotation(rotLocalSphere[i]); | |
posParent[i] = SphereTools.GetPosition(rotLocalSphere[i], planetAttribs.Center, planetAttribs.Radius); | |
tParent[i].rotation = rotParent[i]; | |
tParent[i].position = posParent[i]; | |
tBody[i].localRotation = rotBody[i]; | |
} | |
} | |
public static IEnumerator Load(LoadState loadState, Config config) { | |
loadState.bulletsToLoad = tParent.Length; | |
loadState.bulletsLoaded = 0; | |
Scene sceneBullets = SceneManager.CreateScene("Bullets"); | |
for (int i = 0; i < patternOffset.Length; ++i) { | |
BulletPatternType type = (BulletPatternType)i; | |
if (!typeConfigs.ContainsKey(type)) { | |
continue; | |
} | |
int offset = patternOffset[i]; | |
PatternConfig cfg = typeConfigs[type]; | |
string bulletName = cfg.name; | |
int length = patternLength[i]; | |
int n = offset; | |
for (int b = 0; b < length; ++b) { | |
Instance instance = CreateInstance($"{bulletName}_{b:0000}"); | |
SceneManager.MoveGameObjectToScene(instance.parent, sceneBullets); | |
tParent[n] = instance.parent.transform; | |
tBody[n] = instance.body.transform; | |
tBodyMesh[n] = instance.bodyMesh; | |
tBodyRenderer[n] = instance.bodyRenderer; | |
trail[n] = instance.trailRenderer; | |
// grace[n] = 0f; | |
hidden[n] = false; | |
instanceIds[n] = instance.instanceId; | |
instanceIdMap.Add(instanceIds[n], n); | |
++n; | |
++loadState.bulletsLoaded; | |
if (n % CONST.INSTANTIATES_PER_FRAME == 0) { | |
yield return null; | |
} | |
} | |
cbInit[type].Invoke(cfg, config); | |
} | |
} | |
public struct Instance { | |
public GameObject parent; | |
public GameObject body; | |
public TrailRenderer trailRenderer; | |
public MeshFilter bodyMesh; | |
public MeshRenderer bodyRenderer; | |
public int instanceId; | |
} | |
public static Instance CreateInstance(string name) { | |
Instance instance = new Instance(); | |
instance.parent = new GameObject(name) { | |
layer = LayerHelper.PostProcessing | |
}; | |
instance.instanceId = instance.parent.GetInstanceID(); | |
instance.body = new GameObject("Body") { | |
layer = LayerHelper.PostProcessing | |
}; | |
instance.parent.SetActive(false); | |
TrailRenderer tr = instance.parent.AddComponent<TrailRenderer>(); | |
tr.shadowCastingMode = ShadowCastingMode.Off; | |
tr.receiveShadows = false; | |
tr.motionVectorGenerationMode = MotionVectorGenerationMode.ForceNoMotion; | |
tr.allowOcclusionWhenDynamic = false; | |
instance.trailRenderer = tr; | |
instance.bodyMesh = instance.body.AddComponent<MeshFilter>(); | |
MeshRenderer mr = instance.body.AddComponent<MeshRenderer>(); | |
mr.shadowCastingMode = ShadowCastingMode.Off; | |
mr.receiveShadows = false; | |
mr.lightProbeUsage = LightProbeUsage.Off; | |
tr.reflectionProbeUsage = ReflectionProbeUsage.Off; | |
tr.motionVectorGenerationMode = MotionVectorGenerationMode.ForceNoMotion; | |
tr.allowOcclusionWhenDynamic = false; | |
instance.bodyRenderer = mr; | |
instance.body.transform.SetParent(instance.parent.transform); | |
return instance; | |
} | |
[Conditional("OUTOFBOUNDS")] | |
private static void Throw(object msg) { | |
throw new IndexOutOfRangeException(msg.ToString()); | |
} | |
[Conditional("LOG_BULLETS")] | |
private static void Log(object msg) { | |
FrameLogger.Log(msg.ToString()); | |
} | |
} | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using TerrorSquid.Core; | |
using UnityEngine; | |
namespace TerrorSquid.BulletSystem { | |
public static class PatternLinear { | |
private static Vector2[] direction; | |
private static float[] speed; | |
private static int current; | |
public static void Init(PatternConfig cfg, Config config) { | |
direction = new Vector2[cfg.MaxNum]; | |
speed = new float[cfg.MaxNum]; | |
} | |
public static void Spawn(PatternConfig config, Quaternion rotLocalSphere, Vector2 dir, float dt) { | |
BulletInstance bi = Bullets.GetInstance(config.NameHash, rotLocalSphere, dir); | |
Bullets.Decorate(bi.index, config.BulletDecorator); | |
direction[current] = dir; | |
speed[current] = ((PatternConfigLinear)config).Speed; | |
++current; | |
} | |
public static void Despawn(int from, int to) { | |
direction[to] = direction[from]; | |
speed[to] = speed[from]; | |
--current; | |
} | |
public static void DespawnAll() { | |
current = 0; | |
} | |
public static void Update(float dt, | |
int from, | |
Quaternion[] rotLocalSphere, | |
Quaternion[] rotBody, | |
Quaternion playerRotLocalSphere, | |
Vector2 playerDirection) { | |
for (int i = 0; i < current; ++i) { | |
rotLocalSphere[from + i] = SphereTools.GetLocalSphereRotation(rotLocalSphere[from + i], | |
direction[i], | |
TimeTracks.bulletMovement.DeltaTime * speed[i]); | |
} | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment