An open source Danmaku development kit for Unity3D.
0
fork

Configure Feed

Select the types of activity you want to include in your feed.

Optimizations and Editor Fixes

james713 b97a4f45 1c16230c

+643 -203
+142
Assets/DanmakU/Editor/RadiansEditor.cs
··· 1 + using System.Collections; 2 + using System.Collections.Generic; 3 + using UnityEngine; 4 + using UnityEditor; 5 + 6 + namespace DanmakU { 7 + 8 + [CanEditMultipleObjects] 9 + [CustomPropertyDrawer(typeof(RadiansAttribute))] 10 + internal class RadiansEditor : PropertyDrawer { 11 + 12 + const float buttonSize = 30f; 13 + 14 + Dictionary<string, bool> _propertyType; 15 + 16 + public override void OnGUI(Rect position, SerializedProperty property, GUIContent label) { 17 + var min = property.FindPropertyRelative("_min"); 18 + var max = property.FindPropertyRelative("_max"); 19 + 20 + _propertyType = _propertyType ?? (_propertyType = new Dictionary<string, bool>()); 21 + 22 + switch (property.propertyType) { 23 + case SerializedPropertyType.Float: 24 + var degVal = property.floatValue * Mathf.Rad2Deg; 25 + EditorGUI.showMixedValue = property.hasMultipleDifferentValues; 26 + degVal = EditorGUI.FloatField(position, label, degVal); 27 + EditorGUI.showMixedValue = false; 28 + if (property.hasMultipleDifferentValues) { 29 + property.floatValue = degVal * Mathf.Deg2Rad; 30 + } 31 + break; 32 + default: 33 + if (min != null && max != null) { 34 + bool isRange; 35 + if (!_propertyType.TryGetValue(property.propertyPath, out isRange)) { 36 + isRange = !Mathf.Approximately(min.floatValue, max.floatValue); 37 + _propertyType.Add(property.propertyPath, isRange); 38 + } 39 + var values = new[] { min.floatValue * Mathf.Rad2Deg, max.floatValue * Mathf.Rad2Deg }; 40 + _propertyType[property.propertyPath] = DrawRangeEditor(position, property, label, isRange, values); 41 + if (!min.hasMultipleDifferentValues) min.floatValue = values[0] * Mathf.Deg2Rad; 42 + if (!max.hasMultipleDifferentValues) max.floatValue = values[1] * Mathf.Deg2Rad; 43 + } else { 44 + EditorGUI.PropertyField(position, property, label); 45 + } 46 + break; 47 + } 48 + } 49 + 50 + static bool DrawRangeEditor(Rect position, SerializedProperty property, GUIContent label, bool isRange, float[] values) { 51 + var fieldPosition = position; 52 + var buttonPosition = position; 53 + fieldPosition.width -= buttonSize; 54 + buttonPosition.x += fieldPosition.width; 55 + buttonPosition.width = buttonSize; 56 + 57 + var min = property.FindPropertyRelative("_min"); 58 + var max = property.FindPropertyRelative("_max"); 59 + 60 + EditorGUI.BeginProperty(position, label, property); 61 + if (isRange) { 62 + MultiFloatField(fieldPosition, label, 63 + new[] { new GUIContent("-"), new GUIContent("+")}, 64 + new[] { min.hasMultipleDifferentValues, max.hasMultipleDifferentValues }, 65 + values); 66 + } else { 67 + EditorGUI.showMixedValue = min.hasMultipleDifferentValues || max.hasMultipleDifferentValues; 68 + values[0] = values[1] = EditorGUI.FloatField(fieldPosition, label, values[0]); 69 + EditorGUI.showMixedValue = false; 70 + } 71 + if (GUI.Button(buttonPosition, isRange ? "\u2194" : "\u2022")) { 72 + isRange = !isRange; 73 + if (!isRange) { 74 + values[0] = values[1] = (values[0] + values[1]) / 2; 75 + } 76 + } 77 + EditorGUI.EndProperty(); 78 + return isRange; 79 + } 80 + 81 + static void MultiFloatField(Rect position, GUIContent label, GUIContent[] subLabels, bool[] mixed, float[] values) { 82 + int controlId = GUIUtility.GetControlID("foldout".GetHashCode(), FocusType.Passive, position); 83 + position = MultiFieldPrefixLabel(position, controlId, label, subLabels.Length); 84 + position.height = 16f; 85 + MultiFloatField(position, subLabels, mixed, values); 86 + } 87 + 88 + static void MultiFloatField(Rect position, GUIContent[] subLabels, bool[] mixed, float[] values) { 89 + int length = values.Length; 90 + float num = (position.width - (float) (length - 1) * 2f) / (float) length; 91 + Rect position1 = new Rect(position); 92 + position1.width = num; 93 + float labelWidth1 = EditorGUIUtility.labelWidth; 94 + int indentLevel = EditorGUI.indentLevel; 95 + EditorGUIUtility.labelWidth = 13f; 96 + EditorGUI.indentLevel = 0; 97 + for (int index = 0; index < values.Length; ++index) { 98 + EditorGUI.showMixedValue = mixed[index]; 99 + values[index] = EditorGUI.FloatField(position1, subLabels[index], values[index]); 100 + EditorGUI.showMixedValue = false; 101 + position1.x += num + 2f; 102 + } 103 + EditorGUIUtility.labelWidth = labelWidth1; 104 + EditorGUI.indentLevel = indentLevel; 105 + } 106 + 107 + static bool LabelHasContent(GUIContent label) { 108 + if (label == null || label.text != string.Empty) 109 + return true; 110 + return label.image != null; 111 + } 112 + 113 + static Rect MultiFieldPrefixLabel(Rect totalPosition, int id, GUIContent label, int columns) { 114 + if (!LabelHasContent(label)) 115 + return EditorGUI.IndentedRect(totalPosition); 116 + var indent = EditorGUI.indentLevel * 15f; 117 + if (EditorGUIUtility.wideMode) { 118 + Rect labelPosition = new Rect(totalPosition.x + indent, totalPosition.y, EditorGUIUtility.labelWidth - indent, 16f); 119 + Rect rect = totalPosition; 120 + rect.xMin += EditorGUIUtility.labelWidth; 121 + if (columns > 1) { 122 + --labelPosition.width; 123 + --rect.xMin; 124 + } 125 + if (columns == 2) { 126 + float num = (float) (((double) rect.width - 4.0) / 3.0); 127 + rect.xMax -= num + 2f; 128 + } 129 + EditorGUI.HandlePrefixLabel(totalPosition, labelPosition, label, id); 130 + return rect; 131 + } 132 + Rect labelPosition1 = new Rect(totalPosition.x + indent, totalPosition.y, totalPosition.width - indent, 16f); 133 + Rect rect1 = totalPosition; 134 + rect1.xMin += indent + 15f; 135 + rect1.yMin += 16f; 136 + EditorGUI.HandlePrefixLabel(totalPosition, labelPosition1, label, id); 137 + return rect1; 138 + } 139 + 140 + } 141 + 142 + }
+11
Assets/DanmakU/Editor/RadiansEditor.cs.meta
··· 1 + fileFormatVersion: 2 2 + guid: 9e920fb2cbaa4e34289b8d8cdf2e9452 3 + MonoImporter: 4 + externalObjects: {} 5 + serializedVersion: 2 6 + defaultReferences: [] 7 + executionOrder: 0 8 + icon: {instanceID: 0} 9 + userData: 10 + assetBundleName: 11 + assetBundleVariant:
+84 -17
Assets/DanmakU/Editor/RangeEditor.cs
··· 5 5 6 6 namespace DanmakU { 7 7 8 + [CanEditMultipleObjects] 8 9 [CustomPropertyDrawer(typeof(Range))] 9 - public class RangeDrawer : PropertyDrawer { 10 + internal class RangeDrawer : PropertyDrawer { 10 11 11 12 const float buttonSize = 30f; 12 13 13 14 Dictionary<string, bool> _propertyType; 14 15 15 16 public override void OnGUI(Rect position, SerializedProperty property, GUIContent label) { 16 - var fieldPosition = position; 17 - var buttonPosition = position; 18 - fieldPosition.width -= buttonSize; 19 - buttonPosition.x += fieldPosition.width; 20 - buttonPosition.width = buttonSize; 21 - 22 17 var min = property.FindPropertyRelative("_min"); 23 18 var max = property.FindPropertyRelative("_max"); 24 19 25 - if (_propertyType == null) 26 - _propertyType = new Dictionary<string, bool>(); 20 + _propertyType = _propertyType ?? (_propertyType = new Dictionary<string, bool>()); 27 21 28 22 bool isRange; 29 23 if (!_propertyType.TryGetValue(property.propertyPath, out isRange)) { ··· 31 25 _propertyType.Add(property.propertyPath, isRange); 32 26 } 33 27 28 + _propertyType[property.propertyPath] = DrawRangeEditor(position, property, label, isRange); 29 + } 30 + 31 + static bool DrawRangeEditor(Rect position, SerializedProperty property, GUIContent label, bool isRange) { 32 + var fieldPosition = position; 33 + var buttonPosition = position; 34 + fieldPosition.width -= buttonSize; 35 + buttonPosition.x += fieldPosition.width; 36 + buttonPosition.width = buttonSize; 37 + 38 + var min = property.FindPropertyRelative("_min"); 39 + var max = property.FindPropertyRelative("_max"); 40 + 41 + EditorGUI.showMixedValue = property.hasMultipleDifferentValues; 34 42 EditorGUI.BeginProperty(position, label, property); 35 43 if (isRange) { 36 - var values = new[] { min.floatValue, max.floatValue }; 37 - EditorGUI.MultiFloatField(fieldPosition, label, 38 - new[] { new GUIContent("-"), new GUIContent("+")}, 39 - values); 40 - min.floatValue = values[0]; 41 - max.floatValue = values[1]; 44 + MultiFloatField(fieldPosition, label, 45 + new[] { new GUIContent("-"), new GUIContent("+")}, 46 + new[] { min, max }); 42 47 } else { 43 - var value = EditorGUI.FloatField(fieldPosition, label ,min.floatValue); 48 + var multiEditing = min.hasMultipleDifferentValues || max.hasMultipleDifferentValues; 49 + EditorGUI.showMixedValue = multiEditing; 50 + var value = EditorGUI.FloatField(fieldPosition, label ,min.floatValue); 51 + if (!min.hasMultipleDifferentValues) { 44 52 min.floatValue = value; 45 53 max.floatValue = value; 54 + } 46 55 } 56 + EditorGUI.showMixedValue = false; 47 57 if (GUI.Button(buttonPosition, isRange ? "\u2194" : "\u2022")) { 48 58 isRange = !isRange; 49 59 if (!isRange) { ··· 51 61 min.floatValue = average; 52 62 max.floatValue = average; 53 63 } 54 - _propertyType[property.propertyPath] = isRange; 55 64 } 56 65 EditorGUI.EndProperty(); 66 + return isRange; 67 + } 68 + 69 + static void MultiFloatField(Rect position, GUIContent label, GUIContent[] subLabels, SerializedProperty[] properties) { 70 + int controlId = GUIUtility.GetControlID("foldout".GetHashCode(), FocusType.Passive, position); 71 + position = MultiFieldPrefixLabel(position, controlId, label, subLabels.Length); 72 + position.height = 16f; 73 + MultiFloatField(position, subLabels, properties); 74 + } 75 + 76 + static void MultiFloatField(Rect position, GUIContent[] subLabels, SerializedProperty[] properties) { 77 + int length = properties.Length; 78 + float num = (position.width - (float) (length - 1) * 2f) / (float) length; 79 + Rect position1 = new Rect(position); 80 + position1.width = num; 81 + float labelWidth1 = EditorGUIUtility.labelWidth; 82 + int indentLevel = EditorGUI.indentLevel; 83 + EditorGUIUtility.labelWidth = 13f; 84 + EditorGUI.indentLevel = 0; 85 + for (int index = 0; index < properties.Length; ++index) { 86 + EditorGUI.PropertyField(position1, properties[index], subLabels[index], false); 87 + position1.x += num + 2f; 88 + } 89 + EditorGUIUtility.labelWidth = labelWidth1; 90 + EditorGUI.indentLevel = indentLevel; 91 + } 92 + 93 + static bool LabelHasContent(GUIContent label) { 94 + if (label == null || label.text != string.Empty) 95 + return true; 96 + return label.image != null; 97 + } 98 + 99 + static Rect MultiFieldPrefixLabel(Rect totalPosition, int id, GUIContent label, int columns) { 100 + if (!LabelHasContent(label)) 101 + return EditorGUI.IndentedRect(totalPosition); 102 + var indent = EditorGUI.indentLevel * 15f; 103 + if (EditorGUIUtility.wideMode) { 104 + Rect labelPosition = new Rect(totalPosition.x + indent, totalPosition.y, EditorGUIUtility.labelWidth - indent, 16f); 105 + Rect rect = totalPosition; 106 + rect.xMin += EditorGUIUtility.labelWidth; 107 + if (columns > 1) { 108 + --labelPosition.width; 109 + --rect.xMin; 110 + } 111 + if (columns == 2) { 112 + float num = (float) (((double) rect.width - 4.0) / 3.0); 113 + rect.xMax -= num + 2f; 114 + } 115 + EditorGUI.HandlePrefixLabel(totalPosition, labelPosition, label, id); 116 + return rect; 117 + } 118 + Rect labelPosition1 = new Rect(totalPosition.x + indent, totalPosition.y, totalPosition.width - indent, 16f); 119 + Rect rect1 = totalPosition; 120 + rect1.xMin += indent + 15f; 121 + rect1.yMin += 16f; 122 + EditorGUI.HandlePrefixLabel(totalPosition, labelPosition1, label, id); 123 + return rect1; 57 124 } 58 125 59 126 }
+1 -2
Assets/DanmakU/Runtime/Core/DanmakuPool.cs
··· 163 163 var count = ActiveCount; 164 164 if (count <= 0) return dependency; 165 165 new NativeSlice<Vector2>(OldPositions, 0, count).CopyFrom(new NativeSlice<Vector2>(Positions, 0, count)); 166 - var rotate = new RotateDanmaku(this).Schedule(count, kBatchSize, dependency); 167 - var move = new MoveDanmaku(this).Schedule(count, kBatchSize, rotate); 166 + var move = new MoveDanmaku(this).Schedule(count, kBatchSize, dependency); 168 167 var boundsCheck = new BoundsCheckDanmaku(this).Schedule(count, kBatchSize, move); 169 168 var transforms = new ComputeDanmakuTranforms(this).Schedule(count, kBatchSize, move); 170 169 dependency = JobHandle.CombineDependencies(boundsCheck, transforms);
-19
Assets/DanmakU/Runtime/Core/DanmakuRenderer.cs
··· 88 88 layer: layer); 89 89 } 90 90 91 - // internal void Render(Camera camera) { 92 - // var mesh = GetMesh(); 93 - // var propertyBlock = GetMaterialPropertyBlock(); 94 - // PrepareMaterial(GetRenderMaterial()); 95 - // if (mesh == null || renderMaterial == null) return; 96 - // #if UNITY_EDITOR 97 - // if (!EditorApplication.isPlaying && this != null) { 98 - // colorCache[0] = Color; 99 - // transformCache[0] = transform.worldToLocalMatrix; 100 - // propertyBlock.SetVectorArray("_Color", colorCache); 101 - // Graphics.DrawMeshInstanced(mesh, 0, renderMaterial, transformCache, 102 - // count: 1, 103 - // properties: propertyBlock, 104 - // castShadows: ShadowCastingMode.Off, 105 - // receiveShadows: false, 106 - // layer: gameObject.layer); 107 - // return; 108 - // } 109 - // #endif 110 91 } 111 92 112 93 }
+10 -3
Assets/DanmakU/Runtime/Core/Jobs/BoundsCheckDanmaku.cs
··· 7 7 internal struct BoundsCheckDanmaku : IJobParallelFor { 8 8 9 9 public float DeltaTime; 10 - public Bounds2D Bounds; 11 10 [ReadOnly] public NativeArray<Vector2> Positions; 12 11 public NativeArray<float> Times; 12 + 13 + Vector2 min; 14 + Vector2 max; 13 15 14 16 public BoundsCheckDanmaku(DanmakuPool pool) { 15 17 DeltaTime = Time.deltaTime; 16 - Bounds = DanmakuManager.Instance.Bounds; 17 18 Times = pool.Times; 18 19 Positions = pool.Positions; 20 + 21 + var bounds = DanmakuManager.Instance.Bounds; 22 + min = bounds.Min; 23 + max = bounds.Max; 19 24 } 20 25 21 26 public void Execute(int index) { 22 - if (Bounds.Contains(Positions[index])) { 27 + var position = Positions[index]; 28 + if (position.x >= min.x && position.x <= max.x && 29 + position.y >= min.y && position.y <= max.y) { 23 30 Times[index] += DeltaTime; 24 31 } else { 25 32 Times[index] = float.MinValue;
+19 -11
Assets/DanmakU/Runtime/Core/Jobs/ComputeDanmakuTransforms.cs
··· 1 1 using UnityEngine; 2 2 using Unity.Jobs; 3 3 using Unity.Collections; 4 + using Unity.Collections.LowLevel.Unsafe; 4 5 5 6 namespace DanmakU { 6 7 ··· 16 17 Transforms = pool.Transforms; 17 18 } 18 19 19 - public void Execute(int index) { 20 + public unsafe void Execute(int index) { 20 21 var position = Positions[index]; 21 22 var direction = Directions[index]; 22 23 23 - var transform = new Matrix4x4(); 24 - transform[0, 0] = direction.x; 25 - transform[0, 1] = -direction.y; 26 - transform[1, 0] = direction.y; 27 - transform[1, 1] = direction.x; 28 - transform[2, 2] = 1.0f; 29 - transform[3, 3] = 1; 30 - transform[0, 3] = position.x; 31 - transform[1, 3] = position.y; 24 + var floatPtr = (float*)((Matrix4x4*)Transforms.GetUnsafePtr() + index); 32 25 33 - Transforms[index] = transform; 26 + *floatPtr++ = direction.x; // 0, 0 27 + *floatPtr++ = direction.y; // 0, 1 28 + *floatPtr++ = 0f; // 0, 2 29 + *floatPtr++ = 0f; // 0, 3 30 + *floatPtr++ = -direction.y; // 1, 0 31 + *floatPtr++ = direction.x; // 1, 1 32 + *floatPtr++ = 0f; // 1, 2 33 + *floatPtr++ = 0f; // 1, 3 34 + *floatPtr++ = 0f; // 2, 0 35 + *floatPtr++ = 0f; // 2, 1 36 + *floatPtr++ = 1f; // 2, 2 37 + *floatPtr++ = 0f; // 2, 3 38 + *floatPtr++ = position.x; // 3, 0 39 + *floatPtr++ = position.y; // 3, 1 40 + *floatPtr++ = 0f; // 3, 2 41 + *floatPtr = 1f; // 3, 3 34 42 } 35 43 36 44 }
+5 -3
Assets/DanmakU/Runtime/Core/Jobs/DestroyDanmaku.cs
··· 3 3 using UnityEngine; 4 4 using Unity.Jobs; 5 5 using Unity.Collections; 6 + using Unity.Collections.LowLevel.Unsafe; 6 7 7 8 namespace DanmakU { 8 9 ··· 29 30 Colors = pool.Colors; 30 31 } 31 32 32 - public void Execute() { 33 - var activeCount = ActiveCountArray[0]; 33 + public unsafe void Execute() { 34 + var activeCount = Mathf.Max(0, ActiveCountArray[0]); 35 + var timePtr = (float*)Times.GetUnsafeReadOnlyPtr(); 34 36 for (var i = 0; i < activeCount; i++) { 35 - if (Times[i] > 0) continue; 37 + if (*(timePtr++) >= 0) continue; 36 38 activeCount--; 37 39 InitialStates[i] = InitialStates[activeCount]; 38 40 Times[i] = Times[activeCount];
+19 -3
Assets/DanmakU/Runtime/Core/Jobs/MoveDanmaku.cs
··· 1 1 using Unity.Jobs; 2 2 using Unity.Collections; 3 + using Unity.Collections.LowLevel.Unsafe; 3 4 using UnityEngine; 4 5 5 6 namespace DanmakU { ··· 9 10 public float DeltaTime; 10 11 11 12 public NativeArray<Vector2> Positions; 12 - [ReadOnly] public NativeArray<Vector2> Directions; 13 + public NativeArray<float> Rotations; 14 + [WriteOnly] public NativeArray<Vector2> Directions; 13 15 [ReadOnly] public NativeArray<float> Speeds; 16 + [ReadOnly] public NativeArray<float> AngularSpeeds; 14 17 15 18 public MoveDanmaku(DanmakuPool pool) { 16 19 DeltaTime = Time.deltaTime; 17 20 Positions = pool.Positions; 21 + Rotations = pool.Rotations; 18 22 Directions = pool.Directions; 19 23 Speeds = pool.Speeds; 24 + AngularSpeeds = pool.AngularSpeeds; 20 25 } 21 26 22 - public void Execute(int index) { 23 - Positions[index] += Speeds[index] * Directions[index] * DeltaTime; 27 + public unsafe void Execute(int index) { 28 + var positionPtr = (float*)Positions.GetUnsafePtr() + (index * 2); 29 + var directionPtr = (float*)Directions.GetUnsafePtr() + (index * 2); 30 + var rotationPtr = (float*)Rotations.GetUnsafePtr() + index; 31 + var speed = Speeds[index]; 32 + var rotation = *rotationPtr + AngularSpeeds[index] * DeltaTime; 33 + var dirX = Mathf.Cos(rotation); 34 + var dirY = Mathf.Sin(rotation); 35 + *rotationPtr = rotation; 36 + *positionPtr++ += speed * dirX * DeltaTime; 37 + *positionPtr += speed * dirY * DeltaTime; 38 + *directionPtr++ = dirX; 39 + *directionPtr = dirY; 24 40 } 25 41 26 42 }
-30
Assets/DanmakU/Runtime/Core/Jobs/RotateDanmaku.cs
··· 1 - using UnityEngine; 2 - using Unity.Jobs; 3 - using Unity.Collections; 4 - 5 - namespace DanmakU { 6 - 7 - internal struct RotateDanmaku : IJobParallelFor { 8 - 9 - public float DeltaTime; 10 - 11 - public NativeArray<float> Rotations; 12 - [ReadOnly] public NativeArray<float> AngularSpeeds; 13 - [WriteOnly] public NativeArray<Vector2> Directions; 14 - 15 - public RotateDanmaku(DanmakuPool pool) { 16 - DeltaTime = Time.deltaTime; 17 - Rotations = pool.Rotations; 18 - AngularSpeeds = pool.AngularSpeeds; 19 - Directions = pool.Directions; 20 - } 21 - 22 - public void Execute(int index) { 23 - var rotation = Rotations[index] + AngularSpeeds[index] * DeltaTime; 24 - Directions[index] = RotationUtiliity.ToUnitVector(rotation); 25 - Rotations[index] = rotation; 26 - } 27 - 28 - } 29 - 30 - }
+1 -1
Assets/DanmakU/Runtime/Core/Jobs/RotateDanmaku.cs.meta Assets/DanmakU/Runtime/Fireables/Shapes/Line.cs.meta
··· 1 1 fileFormatVersion: 2 2 - guid: 182bd4d60efdfcd448d0d786e965e2d9 2 + guid: e9cc5afd270b9aa4386bdc423f6e7550 3 3 MonoImporter: 4 4 externalObjects: {} 5 5 serializedVersion: 2
+1 -16
Assets/DanmakU/Runtime/Core/RotationUtil.cs
··· 8 8 9 9 [MethodImpl(MethodImplOptions.AggressiveInlining)] 10 10 public static Vector2 ToUnitVector(float rotation) { 11 - const float HalfPI = Mathf.PI / 2; 12 - return new Vector2(SinHP(rotation + HalfPI), SinHP(rotation)); 13 - } 14 - 15 - /// <summary> 16 - /// A fast approximate sine function. 17 - /// </summary> 18 - [MethodImpl(MethodImplOptions.AggressiveInlining)] 19 - public static float SinHP(float t) { 20 - const float TwoPI = Mathf.PI * 2; 21 - t = (t % TwoPI + TwoPI) % TwoPI; 22 - t = t - Mathf.PI; 23 - float sin = t * (1.27323954f - Mathf.Sign(t) * 0.405284735f * t); 24 - float sinSign = Mathf.Sign(sin); 25 - sin *= sinSign * 0.255f * (sin - sinSign) + 1; 26 - return sin; 11 + return new Vector2(Mathf.Cos(rotation), Mathf.Sin(rotation)); 27 12 } 28 13 29 14 }
+8 -3
Assets/DanmakU/Runtime/DanmakU.asmdef
··· 1 - { 2 - "name": "DanmakU" 3 - } 1 + { 2 + "name": "DanmakU", 3 + "references": [], 4 + "optionalUnityReferences": [], 5 + "includePlatforms": [], 6 + "excludePlatforms": [], 7 + "allowUnsafeCode": true 8 + }
+64
Assets/DanmakU/Runtime/DanmakuEmitter.cs
··· 1 + using System.Collections; 2 + using System.Collections.Generic; 3 + using DanmakU.Fireables; 4 + using UnityEngine; 5 + 6 + namespace DanmakU { 7 + 8 + [AddComponentMenu("DanmakU/Danmaku Emitter")] 9 + public class DanmakuEmitter : DanmakuBehaviour { 10 + 11 + public DanmakuPrefab DanmakuType; 12 + 13 + public Range Speed = 5f; 14 + public Range AngularSpeed; 15 + public Color Color = Color.white; 16 + public Range FireRate = 5; 17 + public float FrameRate; 18 + public Arc Arc; 19 + public Line Line; 20 + 21 + float timer; 22 + DanmakuConfig config; 23 + IFireable fireable; 24 + 25 + /// <summary> 26 + /// Start is called on the frame when a script is enabled just before 27 + /// any of the Update methods is called the first time. 28 + /// </summary> 29 + void Start() { 30 + if (DanmakuType == null) { 31 + Debug.LogWarning($"Emitter doesn't have a valid DanmakuPrefab", this); 32 + return; 33 + } 34 + var set = CreateSet(DanmakuType); 35 + set.AddModifiers(GetComponents<IDanmakuModifier>()); 36 + fireable = Arc.Of(Line).Of(set); 37 + } 38 + 39 + /// <summary> 40 + /// Update is called every frame, if the MonoBehaviour is enabled. 41 + /// </summary> 42 + void Update() { 43 + if (fireable == null) return; 44 + var deltaTime = Time.deltaTime; 45 + if (FrameRate > 0) { 46 + deltaTime = 1f / FrameRate; 47 + } 48 + timer -= deltaTime; 49 + if (timer < 0) { 50 + config = new DanmakuConfig { 51 + Position = transform.position, 52 + Rotation = transform.rotation.eulerAngles.z * Mathf.Deg2Rad, 53 + Speed = Speed, 54 + AngularSpeed = AngularSpeed, 55 + Color = Color 56 + }; 57 + fireable.Fire(config); 58 + timer = 1f / FireRate.GetValue(); 59 + } 60 + } 61 + 62 + } 63 + 64 + }
+11
Assets/DanmakU/Runtime/DanmakuEmitter.cs.meta
··· 1 + fileFormatVersion: 2 2 + guid: 56d35b1ef2eef8249b0ba1b88e74fe60 3 + MonoImporter: 4 + externalObjects: {} 5 + serializedVersion: 2 6 + defaultReferences: [] 7 + executionOrder: 0 8 + icon: {instanceID: 0} 9 + userData: 10 + assetBundleName: 11 + assetBundleVariant:
+4 -4
Assets/DanmakU/Runtime/DanmakuState.cs
··· 10 10 public struct DanmakuConfig { 11 11 12 12 public Vector2 Position; 13 - public Range Rotation; 13 + [Radians] public Range Rotation; 14 14 public Range Speed; 15 - public Range AngularSpeed; 15 + [Radians] public Range AngularSpeed; 16 16 public Color Color; 17 17 18 18 /// <summary> ··· 37 37 [Serializable] 38 38 public struct DanmakuState { 39 39 public Vector2 Position; 40 - public float Rotation; 40 + [Radians] public float Rotation; 41 41 public float Speed; 42 - public float AngularSpeed; 42 + [Radians] public float AngularSpeed; 43 43 public Color Color; 44 44 } 45 45
+11 -6
Assets/DanmakU/Runtime/Fireables/Shapes/Arc.cs
··· 7 7 [Serializable] 8 8 public class Arc : Fireable { 9 9 10 - public Range Count; 11 - public Range ArcLength; 10 + public Range Count = 1; 11 + [Radians] public Range ArcLength; 12 12 public Range Radius; 13 13 14 14 public Arc(Range count, Range arcLength, Range radius) { ··· 20 20 public override void Fire(DanmakuConfig state) { 21 21 float radius = Radius.GetValue(); 22 22 int count = Mathf.RoundToInt(Count.GetValue()); 23 + if (count == 0) return; 24 + if (count == 1) { 25 + Subfire(state); 26 + return; 27 + } 23 28 float arcLength = ArcLength.GetValue(); 24 29 var rotation = state.Rotation.GetValue(); 25 30 var start = rotation - arcLength / 2; 26 - var currentState = state; 27 31 for (int i = 0; i < count; i++) { 28 - var angle = start + i * (arcLength / count); 29 - state.Position = state.Position + (radius * RotationUtiliity.ToUnitVector(angle)); 30 - state.Rotation = angle; 32 + var angle = start + i * (arcLength / (count - 1)); 33 + var currentState = state; 34 + currentState.Position = state.Position + (radius * RotationUtiliity.ToUnitVector(angle)); 35 + currentState.Rotation = angle; 31 36 Subfire(currentState); 32 37 } 33 38 }
+1 -1
Assets/DanmakU/Runtime/Fireables/Shapes/Circle.cs
··· 8 8 [Serializable] 9 9 public class Circle : Fireable { 10 10 11 - public Range Count; 11 + public Range Count = 1; 12 12 public Range Radius; 13 13 14 14 public Circle(Range count, Range radius) {
+23
Assets/DanmakU/Runtime/Fireables/Shapes/Line.cs
··· 1 + using System; 2 + using UnityEngine; 3 + 4 + namespace DanmakU.Fireables { 5 + 6 + [Serializable] 7 + public class Line : Fireable { 8 + 9 + public Range Count = 1; 10 + public Range DeltaSpeed; 11 + 12 + public override void Fire(DanmakuConfig config) { 13 + var count = Mathf.RoundToInt(Count.GetValue()); 14 + var deltaSpeed = DeltaSpeed.GetValue(); 15 + for (var i = 0; i < count; i++) { 16 + config.Speed += deltaSpeed; 17 + Subfire(config); 18 + } 19 + } 20 + 21 + } 22 + 23 + }
+1 -1
Assets/DanmakU/Runtime/Fireables/Shapes/Ring.cs
··· 8 8 [Serializable] 9 9 public class Ring : Fireable { 10 10 11 - public Range Count; 11 + public Range Count = 1; 12 12 public Range Radius; 13 13 14 14 public Ring(Range count, Range radius) {
+23 -5
Assets/DanmakU/Runtime/Modifiers/DanmakuAcceleration.cs
··· 19 19 public JobHandle UpdateDannmaku(DanmakuPool pool, JobHandle dependency = default(JobHandle)) { 20 20 var acceleration = Acceleration * Time.deltaTime; 21 21 if (acceleration.Approximately(0f)) return dependency; 22 - return new ApplyAcceleration { 23 - Acceleration = acceleration, 24 - Speeds = pool.Speeds 25 - }.Schedule(pool.ActiveCount, DanmakuPool.kBatchSize, dependency); 22 + if (Mathf.Approximately(acceleration.Size, 0f)) { 23 + return new ApplyFixedAcceleration { 24 + Acceleration = acceleration.Center, 25 + Speeds = pool.Speeds 26 + }.Schedule(pool.ActiveCount, DanmakuPool.kBatchSize, dependency); 27 + } else { 28 + return new ApplyRandomAcceleration { 29 + Acceleration = acceleration.Center, 30 + Speeds = pool.Speeds 31 + }.Schedule(pool.ActiveCount, DanmakuPool.kBatchSize, dependency); 32 + } 26 33 } 27 34 28 - struct ApplyAcceleration : IJobParallelFor { 35 + struct ApplyFixedAcceleration : IJobParallelFor { 36 + 37 + public float Acceleration; 38 + public NativeArray<float> Speeds; 39 + 40 + public void Execute(int index) { 41 + Speeds[index] += Acceleration; 42 + } 43 + 44 + } 45 + 46 + struct ApplyRandomAcceleration : IJobParallelFor { 29 47 30 48 public Range Acceleration; 31 49 public NativeArray<float> Speeds;
+14
Assets/DanmakU/Runtime/RadiansAttribute.cs
··· 1 + using System; 2 + using UnityEngine; 3 + 4 + namespace DanmakU { 5 + 6 + /// <summary> 7 + /// A PropertyAttribute to automatically allow saving radian values while exposing 8 + /// a field in degrees. 9 + /// </summary> 10 + [AttributeUsage(AttributeTargets.Field)] 11 + public class RadiansAttribute : PropertyAttribute { 12 + } 13 + 14 + }
-35
Assets/DanmakuPoolTest.cs
··· 1 - using DanmakU; 2 - using DanmakU.Fireables; 3 - using System.Collections; 4 - using System.Collections.Generic; 5 - using UnityEngine; 6 - 7 - public class DanmakuPoolTest : DanmakuBehaviour { 8 - 9 - Danmaku danmakuTest; 10 - 11 - public int PoolSize; 12 - public DanmakuPrefab prefab; 13 - public DanmakuConfig State; 14 - public Ring Ring; 15 - public Circle Circle; 16 - IFireable fireable; 17 - float timer; 18 - 19 - void Start () { 20 - fireable = Ring.Of(Circle).Of(CreateSet(prefab)); 21 - } 22 - 23 - /// <summary> 24 - /// Update is called every frame, if the MonoBehaviour is enabled. 25 - /// </summary> 26 - void Update() { 27 - timer += Time.deltaTime; 28 - if (timer > 1/20f) { 29 - State.Rotation += 20 * Mathf.Deg2Rad; 30 - fireable.Fire(State); 31 - timer = 0; 32 - } 33 - } 34 - 35 - }
+1 -1
Assets/DanmakuPoolTest.cs.meta Assets/DanmakU/Runtime/RadiansAttribute.cs.meta
··· 1 1 fileFormatVersion: 2 2 - guid: 12162fd972c15654684d39c8832a9898 2 + guid: 42574055655454444b3e645f49e52b36 3 3 MonoImporter: 4 4 externalObjects: {} 5 5 serializedVersion: 2
+183 -40
Assets/Test Scene.unity
··· 124 124 - component: {fileID: 872241324} 125 125 - component: {fileID: 872241323} 126 126 - component: {fileID: 872241322} 127 - - component: {fileID: 872241321} 128 127 - component: {fileID: 872241320} 129 128 m_Layer: 0 130 129 m_Name: Main Camera ··· 147 146 Bounds: 148 147 Center: {x: 0, y: 0} 149 148 Extents: {x: 100, y: 100} 150 - --- !u!114 &872241321 151 - MonoBehaviour: 152 - m_ObjectHideFlags: 0 153 - m_PrefabParentObject: {fileID: 0} 154 - m_PrefabInternal: {fileID: 0} 155 - m_GameObject: {fileID: 872241319} 156 - m_Enabled: 1 157 - m_EditorHideFlags: 0 158 - m_Script: {fileID: 11500000, guid: 12162fd972c15654684d39c8832a9898, type: 3} 159 - m_Name: 160 - m_EditorClassIdentifier: 161 - PoolSize: 150000 162 - prefab: {fileID: 2040105326} 163 - State: 164 - Position: {x: 0, y: 0} 165 - Rotation: 166 - _min: 0 167 - _max: 0 168 - Speed: 169 - _min: 15 170 - _max: 15 171 - AngularSpeed: 172 - _min: 0 173 - _max: 0 174 - Color: {r: 0.006026864, g: 1, b: 0, a: 1} 175 - Ring: 176 - Count: 177 - _min: 40 178 - _max: 40 179 - Radius: 180 - _min: 0 181 - _max: 0 182 - Circle: 183 - Count: 184 - _min: 15 185 - _max: 15 186 - Radius: 187 - _min: 0 188 - _max: 0 189 149 --- !u!81 &872241322 190 150 AudioListener: 191 151 m_ObjectHideFlags: 0 ··· 249 209 m_Father: {fileID: 0} 250 210 m_RootOrder: 0 251 211 m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} 212 + --- !u!1 &1164331028 213 + GameObject: 214 + m_ObjectHideFlags: 0 215 + m_PrefabParentObject: {fileID: 0} 216 + m_PrefabInternal: {fileID: 0} 217 + serializedVersion: 5 218 + m_Component: 219 + - component: {fileID: 1164331029} 220 + m_Layer: 0 221 + m_Name: Root 222 + m_TagString: Untagged 223 + m_Icon: {fileID: 0} 224 + m_NavMeshLayer: 0 225 + m_StaticEditorFlags: 0 226 + m_IsActive: 1 227 + --- !u!4 &1164331029 228 + Transform: 229 + m_ObjectHideFlags: 0 230 + m_PrefabParentObject: {fileID: 0} 231 + m_PrefabInternal: {fileID: 0} 232 + m_GameObject: {fileID: 1164331028} 233 + m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} 234 + m_LocalPosition: {x: 0, y: 0, z: 0} 235 + m_LocalScale: {x: 1, y: 1, z: 1} 236 + m_Children: 237 + - {fileID: 1364750526} 238 + - {fileID: 1718847665} 239 + m_Father: {fileID: 0} 240 + m_RootOrder: 3 241 + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} 242 + --- !u!1 &1364750525 243 + GameObject: 244 + m_ObjectHideFlags: 0 245 + m_PrefabParentObject: {fileID: 0} 246 + m_PrefabInternal: {fileID: 0} 247 + serializedVersion: 5 248 + m_Component: 249 + - component: {fileID: 1364750526} 250 + - component: {fileID: 1364750527} 251 + - component: {fileID: 1364750528} 252 + m_Layer: 0 253 + m_Name: Emitter 254 + m_TagString: Untagged 255 + m_Icon: {fileID: 0} 256 + m_NavMeshLayer: 0 257 + m_StaticEditorFlags: 0 258 + m_IsActive: 1 259 + --- !u!4 &1364750526 260 + Transform: 261 + m_ObjectHideFlags: 0 262 + m_PrefabParentObject: {fileID: 0} 263 + m_PrefabInternal: {fileID: 0} 264 + m_GameObject: {fileID: 1364750525} 265 + m_LocalRotation: {x: 0, y: 0, z: 0.7071068, w: 0.7071068} 266 + m_LocalPosition: {x: 0, y: 0, z: 0} 267 + m_LocalScale: {x: 1, y: 1, z: 1} 268 + m_Children: [] 269 + m_Father: {fileID: 1164331029} 270 + m_RootOrder: 0 271 + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 90} 272 + --- !u!114 &1364750527 273 + MonoBehaviour: 274 + m_ObjectHideFlags: 0 275 + m_PrefabParentObject: {fileID: 0} 276 + m_PrefabInternal: {fileID: 0} 277 + m_GameObject: {fileID: 1364750525} 278 + m_Enabled: 1 279 + m_EditorHideFlags: 0 280 + m_Script: {fileID: 11500000, guid: 56d35b1ef2eef8249b0ba1b88e74fe60, type: 3} 281 + m_Name: 282 + m_EditorClassIdentifier: 283 + DanmakuType: {fileID: 2040105326} 284 + Speed: 285 + _min: 10 286 + _max: 10 287 + AngularSpeed: 288 + _min: 0 289 + _max: 0 290 + Color: {r: 0.9780209, g: 1, b: 0, a: 1} 291 + FireRate: 292 + _min: 1 293 + _max: 1 294 + FrameRate: 0 295 + Arc: 296 + Count: 297 + _min: 20 298 + _max: 20 299 + ArcLength: 300 + _min: 6.2831855 301 + _max: 6.2831855 302 + Radius: 303 + _min: 0 304 + _max: 0 305 + Line: 306 + Count: 307 + _min: 50 308 + _max: 50 309 + DeltaSpeed: 310 + _min: 2 311 + _max: 2 312 + --- !u!114 &1364750528 313 + MonoBehaviour: 314 + m_ObjectHideFlags: 0 315 + m_PrefabParentObject: {fileID: 0} 316 + m_PrefabInternal: {fileID: 0} 317 + m_GameObject: {fileID: 1364750525} 318 + m_Enabled: 1 319 + m_EditorHideFlags: 0 320 + m_Script: {fileID: 11500000, guid: 6aea72aa749207d448ff891e059cb44c, type: 3} 321 + m_Name: 322 + m_EditorClassIdentifier: 323 + Acceleration: 324 + _min: 5 325 + _max: 5 252 326 --- !u!1 &1481724626 253 327 GameObject: 254 328 m_ObjectHideFlags: 0 ··· 314 388 m_UseColorTemperature: 0 315 389 m_ShadowRadius: 0 316 390 m_ShadowAngle: 0 391 + --- !u!1 &1718847664 392 + GameObject: 393 + m_ObjectHideFlags: 0 394 + m_PrefabParentObject: {fileID: 0} 395 + m_PrefabInternal: {fileID: 0} 396 + serializedVersion: 5 397 + m_Component: 398 + - component: {fileID: 1718847665} 399 + - component: {fileID: 1718847666} 400 + m_Layer: 0 401 + m_Name: Emitter (1) 402 + m_TagString: Untagged 403 + m_Icon: {fileID: 0} 404 + m_NavMeshLayer: 0 405 + m_StaticEditorFlags: 0 406 + m_IsActive: 1 407 + --- !u!4 &1718847665 408 + Transform: 409 + m_ObjectHideFlags: 0 410 + m_PrefabParentObject: {fileID: 0} 411 + m_PrefabInternal: {fileID: 0} 412 + m_GameObject: {fileID: 1718847664} 413 + m_LocalRotation: {x: -0, y: -0, z: 0.7071068, w: 0.7071068} 414 + m_LocalPosition: {x: 0, y: 0, z: 0} 415 + m_LocalScale: {x: 1.0000005, y: 1.0000005, z: 1} 416 + m_Children: [] 417 + m_Father: {fileID: 1164331029} 418 + m_RootOrder: 1 419 + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 90} 420 + --- !u!114 &1718847666 421 + MonoBehaviour: 422 + m_ObjectHideFlags: 0 423 + m_PrefabParentObject: {fileID: 0} 424 + m_PrefabInternal: {fileID: 0} 425 + m_GameObject: {fileID: 1718847664} 426 + m_Enabled: 0 427 + m_EditorHideFlags: 0 428 + m_Script: {fileID: 11500000, guid: 56d35b1ef2eef8249b0ba1b88e74fe60, type: 3} 429 + m_Name: 430 + m_EditorClassIdentifier: 431 + DanmakuType: {fileID: 2040105326} 432 + Speed: 433 + _min: 15 434 + _max: 15 435 + AngularSpeed: 436 + _min: 0 437 + _max: 0 438 + Color: {r: 0.9780209, g: 1, b: 0, a: 1} 439 + FireRate: 440 + _min: 1 441 + _max: 1 442 + FrameRate: 0 443 + Arc: 444 + Count: 445 + _min: 5 446 + _max: 5 447 + ArcLength: 448 + _min: 1.5707964 449 + _max: 1.5707964 450 + Radius: 451 + _min: 0 452 + _max: 0 453 + Line: 454 + Count: 455 + _min: 5 456 + _max: 5 457 + DeltaSpeed: 458 + _min: 10 459 + _max: 10 317 460 --- !u!1 &2040105325 318 461 GameObject: 319 462 m_ObjectHideFlags: 0
+5 -1
ProjectSettings/ProjectSettings.asset
··· 252 252 m_BuildTargetIcons: [] 253 253 m_BuildTargetPlatformIcons: [] 254 254 m_BuildTargetBatching: [] 255 - m_BuildTargetGraphicsAPIs: [] 255 + m_BuildTargetGraphicsAPIs: 256 + - m_BuildTarget: WindowsStandaloneSupport 257 + m_APIs: 02000000 258 + m_Automatic: 1 256 259 m_BuildTargetVRSettings: [] 257 260 m_BuildTargetEnableVuforiaSettings: [] 258 261 openGLRequireES31: 0 ··· 537 540 scriptingBackend: {} 538 541 il2cppCompilerConfiguration: {} 539 542 incrementalIl2cppBuild: {} 543 + allowUnsafeCode: 0 540 544 additionalIl2CppArgs: 541 545 scriptingRuntimeVersion: 1 542 546 apiCompatibilityLevelPerPlatform: {}
+1 -1
ProjectSettings/ProjectVersion.txt
··· 1 - m_EditorVersion: 2018.1.0b7 1 + m_EditorVersion: 2018.1.0b8