├── .gitignore ├── Assets └── _Project │ └── Scripts │ ├── BulletHell │ ├── Bullet.cs │ ├── Bullet.cs.meta │ ├── BulletHellManager.cs │ ├── BulletHellManager.cs.meta │ ├── BulletHellProjectile.cs │ ├── BulletHellProjectile.cs.meta │ ├── BulletPatternGenerator.cs │ ├── BulletPatternGenerator.cs.meta │ ├── PlayerShooter.cs │ └── PlayerShooter.cs.meta │ ├── RaycastBatchProcessor.cs │ └── RaycastBatchProcessor.cs.meta ├── Packages └── manifest.json └── README.md /.gitignore: -------------------------------------------------------------------------------- 1 | # This .gitignore file should be placed at the root of your Unity project directory 2 | # 3 | # Get latest from https://github.com/github/gitignore/blob/main/Unity.gitignore 4 | # 5 | /[Ll]ibrary/ 6 | /[Tt]emp/ 7 | /[Oo]bj/ 8 | /[Bb]uild/ 9 | /[Bb]uildFullScreen/ 10 | /[Bb]uilds/ 11 | /[Ll]ogs/ 12 | /[Uu]ser[Ss]ettings/ 13 | /CCDBuildData/ 14 | 15 | # Ignore everything under Assets except the _Project folder 16 | Assets/* 17 | !Assets/_Project/ 18 | 19 | # MemoryCaptures can get excessive in size. 20 | # They also could contain extremely sensitive data 21 | /[Mm]emoryCaptures/ 22 | 23 | # Recordings can get excessive in size 24 | /[Rr]ecordings/ 25 | 26 | # Uncomment this line if you wish to ignore the asset store tools plugin 27 | # /[Aa]ssets/AssetStoreTools* 28 | 29 | # Autogenerated Jetbrains Rider plugin 30 | /[Aa]ssets/Plugins/Editor/JetBrains* 31 | 32 | # Visual Studio cache directory 33 | .vs/ 34 | 35 | # Gradle cache directory 36 | .gradle/ 37 | 38 | # Autogenerated VS/MD/Consulo solution and project files 39 | ExportedObj/ 40 | .consulo/ 41 | *.csproj 42 | *.unityproj 43 | *.sln 44 | *.suo 45 | *.tmp 46 | *.user 47 | *.userprefs 48 | *.pidb 49 | *.booproj 50 | *.svd 51 | *.pdb 52 | *.mdb 53 | *.opendb 54 | *.VC.db 55 | 56 | # Unity3D generated meta files 57 | *.pidb.meta 58 | *.pdb.meta 59 | *.mdb.meta 60 | 61 | # Unity3D generated file on crash reports 62 | sysinfo.txt 63 | 64 | # Builds 65 | *.apk 66 | *.aab 67 | *.unitypackage 68 | *.app 69 | 70 | # Crashlytics generated file 71 | crashlytics-build.properties 72 | 73 | # Packed Addressables 74 | /[Aa]ssets/[Aa]ddressable[Aa]ssets[Dd]ata/*/*.bin* 75 | 76 | # Temporary auto-generated Android Assets 77 | /[Aa]ssets/[Ss]treamingAssets/aa.meta 78 | /[Aa]ssets/[Ss]treamingAssets/aa/* 79 | 80 | # Custom 81 | Assets/SceneDependencyCache* 82 | Assets/NetCodeGenerated* 83 | .idea/ 84 | .DS_Store 85 | RiderScriptEditorPersistedState.asset 86 | Packages/packages-lock.json 87 | -------------------------------------------------------------------------------- /Assets/_Project/Scripts/BulletHell/Bullet.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using UnityEngine; 3 | 4 | public class Bullet : MonoBehaviour { 5 | public Vector3 direction; 6 | float maxDistance; 7 | Vector3 startPosition; 8 | 9 | public void Initialize(Vector3 position, Vector3 direction, float maxDistance) { 10 | transform.position = position; 11 | this.startPosition = position; 12 | this.direction = direction; 13 | this.maxDistance = maxDistance; 14 | 15 | transform.rotation = Quaternion.LookRotation(direction); 16 | } 17 | 18 | public bool HasTraveledMaxDistance() { 19 | float distanceTraveledSq = (startPosition - transform.position).sqrMagnitude; 20 | return distanceTraveledSq >= maxDistance * maxDistance; 21 | } 22 | } -------------------------------------------------------------------------------- /Assets/_Project/Scripts/BulletHell/Bullet.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: a526f78115c5407fae4e27323eb39d4c 3 | timeCreated: 1728667154 -------------------------------------------------------------------------------- /Assets/_Project/Scripts/BulletHell/BulletHellManager.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using Unity.Burst; 3 | using Unity.Collections; 4 | using Unity.Jobs; 5 | using UnityEngine; 6 | using UnityEngine.Jobs; 7 | using UnityEngine.Pool; 8 | using UnityUtils; 9 | 10 | public class BulletHellManager : Singleton { 11 | #region Settings and Refs 12 | [SerializeField] int bulletCount = 100; // Number of bullets to spawn 13 | [SerializeField] float bulletSpeed = 10f; // Speed of each bullet 14 | [SerializeField] float bulletMaxDistance = 30f; // Maximum distance each bullet can travel 15 | [SerializeField] LayerMask collisionMask; // Layer mask for raycast collision detection 16 | [SerializeField] Transform bulletOrigin; // Origin point for bullet spawning 17 | 18 | [SerializeField] GameObject bulletPrefab; // Bullet prefab to instantiate 19 | [SerializeField] GameObject impactEffectPrefab; // Effect to spawn on bullet impact 20 | #endregion 21 | 22 | ObjectPool bulletPool; 23 | BulletPatternGenerator patternGenerator; 24 | 25 | readonly List activeProjectiles = new List(); 26 | readonly List bulletsToReturn = new List(); 27 | 28 | TransformAccessArray bulletTransforms; 29 | 30 | void Start() { 31 | patternGenerator = new BulletPatternGenerator(new RadialPattern()); 32 | 33 | bulletPool = new ObjectPool( 34 | createFunc: () => { 35 | GameObject bulletObj = Instantiate(bulletPrefab); 36 | bulletObj.SetActive(false); 37 | return bulletObj.GetOrAdd(); 38 | }, 39 | actionOnGet: bullet => bullet.gameObject.SetActive(true), 40 | actionOnRelease: bullet => bullet.gameObject.SetActive(false), 41 | actionOnDestroy: bullet => DestroyBullet(bullet), 42 | collectionCheck: false, 43 | defaultCapacity: bulletCount, 44 | maxSize: bulletCount * 10 45 | ); 46 | } 47 | 48 | void DestroyBullet(Bullet bullet) { 49 | if (bullet) { 50 | Destroy(bullet.gameObject); 51 | } 52 | } 53 | 54 | void Update() { 55 | int subSteps = 5; 56 | float subStepTime = Time.deltaTime / subSteps; 57 | 58 | // Consider caching the TransformAccessArray if possible 59 | using (bulletTransforms = new TransformAccessArray(activeProjectiles.Count)) { 60 | for (int i = activeProjectiles.Count; i-- > 0;) { 61 | Bullet bullet = activeProjectiles[i]; 62 | if (bullet.HasTraveledMaxDistance()) { 63 | ReturnBullet(bullet); 64 | continue; 65 | } 66 | bulletTransforms.Add(bullet.transform); 67 | } 68 | 69 | for (int step = 0; step < subSteps; step++) { 70 | var job = new BulletMoveJob { 71 | deltaTime = subStepTime, 72 | speed = bulletSpeed 73 | }; 74 | 75 | JobHandle jobHandle = job.Schedule(bulletTransforms); 76 | jobHandle.Complete(); 77 | 78 | HandleCollisions(); 79 | } 80 | } 81 | } 82 | 83 | void HandleCollisions() { 84 | Vector3[] origins = new Vector3[activeProjectiles.Count]; 85 | Vector3[] directions = new Vector3[activeProjectiles.Count]; 86 | 87 | for (int i = 0; i < activeProjectiles.Count; i++) { 88 | Bullet bullet = activeProjectiles[i]; 89 | origins[i] = bullet.transform.position; 90 | directions[i] = bullet.direction; 91 | } 92 | 93 | RaycastBatchProcessor.Instance.PerformRaycasts(origins, directions, collisionMask.value, false, false, false, OnRaycastResults); 94 | } 95 | 96 | void OnRaycastResults(RaycastHit[] hits) { 97 | for (int i = hits.Length; i-- > 0;) { 98 | if (hits[i].collider != null) { 99 | ReturnBullet(activeProjectiles[i]); 100 | 101 | // TODO Pool the impact effects 102 | GameObject impactEffect = Instantiate(impactEffectPrefab, hits[i].point, Quaternion.identity); 103 | impactEffect.transform.SetParent(hits[i].collider.transform); 104 | impactEffect.transform.up = hits[i].normal; 105 | Destroy(impactEffect, 2f); 106 | } 107 | } 108 | } 109 | 110 | void ReturnBullet(Bullet bullet) { 111 | bulletsToReturn.Add(bullet); 112 | activeProjectiles.Remove(bullet); 113 | } 114 | 115 | [BurstCompile] 116 | struct BulletMoveJob : IJobParallelForTransform { 117 | public float deltaTime; 118 | public float speed; 119 | 120 | public void Execute(int index, TransformAccess transform) { 121 | Vector3 forward = transform.rotation * Vector3.forward; 122 | transform.position += forward * speed * deltaTime; 123 | } 124 | } 125 | 126 | public void SpawnBulletPattern() { 127 | BulletHellProjectile[] newBullets = patternGenerator.GeneratePattern(bulletOrigin.position, bulletCount, bulletSpeed); 128 | 129 | foreach (BulletHellProjectile projectile in newBullets) { 130 | Bullet bullet = bulletPool.Get(); 131 | bullet.Initialize(projectile.Position, projectile.Direction, bulletMaxDistance); 132 | activeProjectiles.Add(bullet); 133 | } 134 | } 135 | 136 | public void SetPattern(IBulletPattern pattern) => patternGenerator.SetPattern(pattern); 137 | 138 | void LateUpdate() { 139 | foreach (var bullet in bulletsToReturn) { 140 | bulletPool.Release(bullet); 141 | } 142 | bulletsToReturn.Clear(); 143 | } 144 | 145 | void OnDestroy() { 146 | bulletPool.Dispose(); 147 | } 148 | } -------------------------------------------------------------------------------- /Assets/_Project/Scripts/BulletHell/BulletHellManager.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: b064449c8b0047d78ed252414764ced9 3 | timeCreated: 1728667060 -------------------------------------------------------------------------------- /Assets/_Project/Scripts/BulletHell/BulletHellProjectile.cs: -------------------------------------------------------------------------------- 1 | using UnityEngine; 2 | 3 | public class BulletHellProjectile { 4 | public Vector3 Position { get; private set; } 5 | public Vector3 Direction { get; private set; } 6 | public float Speed { get; private set; } 7 | 8 | public BulletHellProjectile(Vector3 startPosition, Vector3 direction, float speed) { 9 | Position = startPosition; 10 | Direction = direction.normalized; 11 | Speed = speed; 12 | } 13 | } -------------------------------------------------------------------------------- /Assets/_Project/Scripts/BulletHell/BulletHellProjectile.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: dc6de93c106c4efb808b93078261dee8 3 | timeCreated: 1728667034 -------------------------------------------------------------------------------- /Assets/_Project/Scripts/BulletHell/BulletPatternGenerator.cs: -------------------------------------------------------------------------------- 1 | using UnityEngine; 2 | 3 | public interface IBulletPattern { 4 | BulletHellProjectile[] GeneratePattern(Vector3 origin, Vector3 forward, int bulletCount, float speed); 5 | } 6 | 7 | public class BulletPatternGenerator { 8 | IBulletPattern bulletPattern; 9 | 10 | public BulletPatternGenerator(IBulletPattern pattern) { 11 | bulletPattern = pattern; 12 | } 13 | 14 | public BulletHellProjectile[] GeneratePattern(Vector3 origin, int bulletCount, float speed) { 15 | return bulletPattern.GeneratePattern(origin, Vector3.forward, bulletCount, speed); 16 | } 17 | 18 | public void SetPattern(IBulletPattern pattern) => bulletPattern = pattern; 19 | } 20 | 21 | public class RadialPattern : IBulletPattern { 22 | public BulletHellProjectile[] GeneratePattern(Vector3 origin, Vector3 forward, int bulletCount, float speed) { 23 | BulletHellProjectile[] bullets = new BulletHellProjectile[bulletCount]; 24 | float angleStep = 360f / bulletCount; // Divide the circle into equal angles 25 | 26 | for (int i = 0; i < bulletCount; i++) { 27 | float angle = i * angleStep; 28 | 29 | // Create a local direction in the x/z plane 30 | Vector3 localDirection = new Vector3(Mathf.Cos(angle * Mathf.Deg2Rad), 0, Mathf.Sin(angle * Mathf.Deg2Rad)).normalized; 31 | 32 | // Rotate the local direction to match the forward direction of the object 33 | Vector3 direction = Quaternion.LookRotation(forward) * localDirection; 34 | 35 | // Initialize the bullet with the calculated position and direction 36 | bullets[i] = new BulletHellProjectile(origin, direction, speed); 37 | } 38 | 39 | return bullets; 40 | } 41 | } 42 | 43 | public class WavePattern : IBulletPattern { 44 | public BulletHellProjectile[] GeneratePattern(Vector3 origin, Vector3 forward, int bulletCount, float speed) { 45 | BulletHellProjectile[] bullets = new BulletHellProjectile[bulletCount]; 46 | float waveFrequency = 0.1f; // Frequency of the wave oscillation 47 | float waveAmplitude = 1f; // Amplitude of wave motion 48 | 49 | for (int i = 0; i < bulletCount; i++) { 50 | float waveOffset = Mathf.Sin(i * waveFrequency) * waveAmplitude; 51 | 52 | // Calculate direction in x/z plane, with wave affecting the x-axis 53 | Vector3 localDirection = new Vector3(waveOffset, 0, 1).normalized; 54 | 55 | // Rotate the local direction to align with the forward direction 56 | Vector3 direction = Quaternion.LookRotation(forward) * localDirection; 57 | 58 | bullets[i] = new BulletHellProjectile(origin, direction, speed); 59 | } 60 | 61 | return bullets; 62 | } 63 | } 64 | 65 | public class SpiralPattern : IBulletPattern { 66 | public BulletHellProjectile[] GeneratePattern(Vector3 origin, Vector3 forward, int bulletCount, float speed) { 67 | BulletHellProjectile[] bullets = new BulletHellProjectile[bulletCount]; 68 | float angleStep = 10f; // Angle between bullets 69 | float radiusStep = 0.1f; // Radius increases per bullet 70 | 71 | for (int i = 0; i < bulletCount; i++) { 72 | float angle = i * angleStep; 73 | float radius = i * radiusStep; // Spiral outwards 74 | 75 | // Calculate direction in x/z plane 76 | Vector3 localDirection = new Vector3(Mathf.Cos(angle * Mathf.Deg2Rad), 0, Mathf.Sin(angle * Mathf.Deg2Rad)).normalized; 77 | 78 | // Rotate local direction to match the forward direction 79 | Vector3 direction = Quaternion.LookRotation(forward) * localDirection; 80 | Vector3 offset = direction * radius; 81 | 82 | bullets[i] = new BulletHellProjectile(origin + offset, direction, speed); 83 | } 84 | 85 | return bullets; 86 | } 87 | } -------------------------------------------------------------------------------- /Assets/_Project/Scripts/BulletHell/BulletPatternGenerator.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 1476055f805646269832f2c304c6a09b 3 | timeCreated: 1728667293 -------------------------------------------------------------------------------- /Assets/_Project/Scripts/BulletHell/PlayerShooter.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using PrimeTween; 3 | using UnityEngine; 4 | 5 | public class PlayerShooter : MonoBehaviour { 6 | [SerializeField] float fireRate = 1f; 7 | float fireCooldown; 8 | 9 | [SerializeField] Transform guns; 10 | 11 | [SerializeField] KeyCode radialPatternKey = KeyCode.Alpha1; 12 | [SerializeField] KeyCode wavePatternKey = KeyCode.Alpha2; 13 | [SerializeField] KeyCode spiralPatternKey = KeyCode.Alpha3; 14 | 15 | Type pattern = typeof(RadialPattern); 16 | 17 | void Update() { 18 | HandlePatternSwitching(); 19 | HandleFiring(); 20 | } 21 | 22 | void HandlePatternSwitching() { 23 | if (Input.GetKeyDown(radialPatternKey)) { 24 | BulletHellManager.Instance.SetPattern(new RadialPattern()); 25 | pattern = typeof(RadialPattern); 26 | Debug.Log("Switched to Radial Pattern"); 27 | } else if (Input.GetKeyDown(wavePatternKey)) { 28 | BulletHellManager.Instance.SetPattern(new WavePattern()); 29 | pattern = typeof(WavePattern); 30 | Debug.Log("Switched to Wave Pattern"); 31 | } else if (Input.GetKeyDown(spiralPatternKey)) { 32 | BulletHellManager.Instance.SetPattern(new SpiralPattern()); 33 | pattern = typeof(SpiralPattern); 34 | Debug.Log("Switched to Spiral Pattern"); 35 | } 36 | } 37 | 38 | void HandleFiring() { 39 | fireCooldown -= Time.deltaTime; 40 | 41 | if (Input.GetKey(KeyCode.Space) && fireCooldown <= 0f) { 42 | BulletHellManager.Instance.SpawnBulletPattern(); 43 | fireCooldown = fireRate; 44 | } 45 | } 46 | } -------------------------------------------------------------------------------- /Assets/_Project/Scripts/BulletHell/PlayerShooter.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 5ac732ca78eb4937886b6b7f49d32069 3 | timeCreated: 1728668243 -------------------------------------------------------------------------------- /Assets/_Project/Scripts/RaycastBatchProcessor.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using UnityEngine; 3 | using Unity.Collections; 4 | using Unity.Jobs; 5 | using UnityUtils; 6 | 7 | public class RaycastBatchProcessor : Singleton { 8 | [SerializeField] int maxRaycastsPerJob = 10000; 9 | 10 | NativeArray rayCommands; 11 | NativeArray sphereCommands; 12 | NativeArray hitResults; 13 | 14 | public void PerformRaycasts( 15 | Vector3[] origins, 16 | Vector3[] directions, 17 | int layerMask, 18 | bool hitBackfaces, 19 | bool hitTriggers, 20 | bool hitMultiFace, 21 | Action callback) { 22 | const float maxDistance = 1f; 23 | int rayCount = Mathf.Min(origins.Length, maxRaycastsPerJob); 24 | 25 | QueryTriggerInteraction queryTriggerInteraction = hitTriggers ? QueryTriggerInteraction.Collide : QueryTriggerInteraction.Ignore; 26 | 27 | using (rayCommands = new NativeArray(rayCount, Allocator.TempJob)) { 28 | QueryParameters parameters = new QueryParameters { 29 | layerMask = layerMask, 30 | hitBackfaces = hitBackfaces, 31 | hitTriggers = queryTriggerInteraction, 32 | hitMultipleFaces = hitMultiFace 33 | }; 34 | 35 | for (int i = 0; i < rayCount; i++) { 36 | rayCommands[i] = new RaycastCommand(origins[i], directions[i], parameters, maxDistance); 37 | } 38 | 39 | ExecuteRaycasts(rayCommands, callback); 40 | } 41 | } 42 | 43 | void ExecuteRaycasts(NativeArray raycastCommands, Action callback) { 44 | int maxHitsPerRaycast = 1; 45 | int totalHitsNeeded = raycastCommands.Length * maxHitsPerRaycast; 46 | 47 | using (hitResults = new NativeArray(totalHitsNeeded, Allocator.TempJob)) { 48 | foreach (RaycastCommand t in raycastCommands) { 49 | Debug.DrawLine(t.from, t.from + t.direction * 1f, Color.red, 0.5f); 50 | } 51 | 52 | JobHandle raycastJobHandle = RaycastCommand.ScheduleBatch(raycastCommands, hitResults, maxHitsPerRaycast); 53 | raycastJobHandle.Complete(); 54 | 55 | if (hitResults.Length > 0) { 56 | RaycastHit[] results = hitResults.ToArray(); 57 | 58 | // for (int i = 0; i < results.Length; i++) { 59 | // if (results[i].collider != null) { 60 | // Debug.Log($"Hit: {results[i].collider.name} at {results[i].point}"); 61 | // Debug.DrawLine(raycastCommands[i].from, results[i].point, Color.green, 1.0f); 62 | // } 63 | // } 64 | 65 | callback?.Invoke(results); 66 | } 67 | } 68 | } 69 | } -------------------------------------------------------------------------------- /Assets/_Project/Scripts/RaycastBatchProcessor.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 3854b99a41f94dbc9296736e1dbd3e72 3 | timeCreated: 1728664067 -------------------------------------------------------------------------------- /Packages/manifest.json: -------------------------------------------------------------------------------- 1 | { 2 | "dependencies": { 3 | "com.gitamend.improvedtimers": "git+https://github.com/adammyhre/Unity-Improved-Timers.git", 4 | "com.gitamend.tools": "file:C:/Unity/Tools", 5 | "com.gitamend.unityutils": "git+https://github.com/adammyhre/Unity-Utils.git", 6 | "com.kylewbanks.scenerefattribute": "git+https://github.com/KyleBanks/scene-ref-attribute.git", 7 | "com.kyrylokuzyk.primetween": "file:../Assets/Plugins/PrimeTween/internal/com.kyrylokuzyk.primetween.tgz", 8 | "com.unity.ai.navigation": "2.0.4", 9 | "com.unity.burst": "1.8.18", 10 | "com.unity.collab-proxy": "2.5.2", 11 | "com.unity.collections": "2.4.3", 12 | "com.unity.dt.app-ui": "1.1.0", 13 | "com.unity.editorcoroutines": "1.0.0", 14 | "com.unity.ide.rider": "3.0.31", 15 | "com.unity.ide.visualstudio": "2.0.22", 16 | "com.unity.inputsystem": "1.11.0", 17 | "com.unity.mathematics": "1.3.2", 18 | "com.unity.multiplayer.center": "1.0.0", 19 | "com.unity.postprocessing": "3.4.0", 20 | "com.unity.recorder": "5.1.1", 21 | "com.unity.render-pipelines.universal": "17.0.3", 22 | "com.unity.shadergraph": "17.0.3", 23 | "com.unity.test-framework": "1.4.5", 24 | "com.unity.timeline": "1.8.7", 25 | "com.unity.ugui": "2.0.0", 26 | "com.unity.visualscripting": "1.9.4", 27 | "com.unity.modules.accessibility": "1.0.0", 28 | "com.unity.modules.ai": "1.0.0", 29 | "com.unity.modules.androidjni": "1.0.0", 30 | "com.unity.modules.animation": "1.0.0", 31 | "com.unity.modules.assetbundle": "1.0.0", 32 | "com.unity.modules.audio": "1.0.0", 33 | "com.unity.modules.cloth": "1.0.0", 34 | "com.unity.modules.director": "1.0.0", 35 | "com.unity.modules.imageconversion": "1.0.0", 36 | "com.unity.modules.imgui": "1.0.0", 37 | "com.unity.modules.jsonserialize": "1.0.0", 38 | "com.unity.modules.particlesystem": "1.0.0", 39 | "com.unity.modules.physics": "1.0.0", 40 | "com.unity.modules.physics2d": "1.0.0", 41 | "com.unity.modules.screencapture": "1.0.0", 42 | "com.unity.modules.terrain": "1.0.0", 43 | "com.unity.modules.terrainphysics": "1.0.0", 44 | "com.unity.modules.tilemap": "1.0.0", 45 | "com.unity.modules.ui": "1.0.0", 46 | "com.unity.modules.uielements": "1.0.0", 47 | "com.unity.modules.umbra": "1.0.0", 48 | "com.unity.modules.unityanalytics": "1.0.0", 49 | "com.unity.modules.unitywebrequest": "1.0.0", 50 | "com.unity.modules.unitywebrequestassetbundle": "1.0.0", 51 | "com.unity.modules.unitywebrequestaudio": "1.0.0", 52 | "com.unity.modules.unitywebrequesttexture": "1.0.0", 53 | "com.unity.modules.unitywebrequestwww": "1.0.0", 54 | "com.unity.modules.vehicles": "1.0.0", 55 | "com.unity.modules.video": "1.0.0", 56 | "com.unity.modules.vr": "1.0.0", 57 | "com.unity.modules.wind": "1.0.0", 58 | "com.unity.modules.xr": "1.0.0" 59 | } 60 | } 61 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Unity Batch Raycasting 2 | 3 | ![BatchRaycast](https://github.com/user-attachments/assets/14e153d7-991b-479f-ace4-8498791cc2f7) 4 | 5 | Optimizing Collision handling in Unity with Batch Raycasting! 6 | 7 | In this video, you'll learn how to efficiently manage projectile movement and collision detection using Unity's Job System and Burst Compiler. We'll use TransformAccessArray to optimize bullet movement and take advantage of parallel processing. You'll see how to split the workload across multiple threads, reduce performance bottlenecks, and ensure accurate collision detection using Raycasts. Whether you're building fast-paced action games or want to improve performance in complex simulations, this tutorial will show you practical steps to level up your game's efficiency. 8 | 9 | ## YouTube 10 | 11 | [**RAYCASTING Made Insanely Fast for Collision Detection!**](https://youtu.be/WrzrtMxLgpc) 12 | 13 | You can also check out my [YouTube channel](https://www.youtube.com/@git-amend?sub_confirmation=1) for more Unity content. 14 | --------------------------------------------------------------------------------