Quantcast
Viewing all articles
Browse latest Browse all 102

Answer by lodendsg

I know this is an old question but its a problem that is ran into offten. The specific case we have is several hundred warships in a space game each with multiple turrets, each turret with multiple barrels and a resonably fast fire rate and projectile lifetime. We implamented a GPU instancing solution and found it to massivly reduce performance impact. The biggest part of the gain is due to there being only 1 gameObject in the scene representing all our projectiles. The following C# code is from our test rig, it has been used in 2017.3.1 succesfuly but isn't optimized so could be further improved Im sure ... never the less its better than pooling assuming your projectiles are simple meshes with an instance enabled material. PS: ConquestBattleConfiguration is just a ScriptableObject we use to store some common settings in this case it stores the layers we test for collision on. public class ProjectileRenderer : MonoBehaviour { [Header("Data")] public ConquestBattleConfiguration Config; public Mesh mesh; public Material material; public float life; public float speed; public float damage; [Header("Instances")] public List projectiles = new List(); public List splashPool = new List(); //Working values private RaycastHit[] rayHitBuffer = new RaycastHit[1]; private Vector3 worldPoint; private Vector3 transPoint; private List bufferedData = new List(); public void SpawnProjectile(Vector3 position, Quaternion rotation, int team, float damageScale) { ProjectileData n = new ProjectileData(); n.pos = position; n.rot = rotation; n.scale = Vector3.one; n.experation = life; n.team = team; n.damage = damage; n.damageScale = damageScale; projectiles.Add(n); } private void Update() { UpdateProjectiles(Time.deltaTime); BatchAndRender(); } private void BatchAndRender() { //If we dont have projectiles to render then just get out if (projectiles.Count <= 0) return; //Clear the batch buffer bufferedData.Clear(); //If we can fit all in 1 batch then do so if (projectiles.Count < 1023) bufferedData.Add(projectiles.Select(p => p.renderData).ToArray()); else { //We need multiple batches int count = projectiles.Count; for (int i = 0; i < count; i += 1023) { if (i + 1023 < count) { Matrix4x4[] tBuffer = new Matrix4x4[1023]; for(int ii = 0; ii < 1023; ii++) { tBuffer[ii] = projectiles[i + ii].renderData; } bufferedData.Add(tBuffer); } else { //last batch Matrix4x4[] tBuffer = new Matrix4x4[count - i]; for (int ii = 0; ii < count - i; ii++) { tBuffer[ii] = projectiles[i + ii].renderData; } bufferedData.Add(tBuffer); } } } //Draw each batch foreach (var batch in bufferedData) Graphics.DrawMeshInstanced(mesh, 0, material, batch, batch.Length); } private void UpdateProjectiles(float tick) { foreach(var projectile in projectiles) { projectile.experation -= tick; if (projectile.experation > 0) { //Sort out the projectiles 'forward' direction transPoint = projectile.rot * Vector3.forward; //See if its going to hit something and if so handle that if (Physics.RaycastNonAlloc(projectile.pos, transPoint, rayHitBuffer, speed * tick, Config.ColliderLayers) > 0) { projectile.experation = -1; worldPoint = rayHitBuffer[0].point; SpawnSplash(worldPoint); ConquestShipCombatController target = rayHitBuffer[0].rigidbody.GetComponent(); if (target.teamId != projectile.team) { target.ApplyDamage(projectile.damage * projectile.damageScale, worldPoint); } } else { //This project wont be hitting anything this tick so just move it forward projectile.pos += transPoint * (speed * tick); } } } //Remove all the projectiles that have hit there experation, can happen due to time or impact projectiles.RemoveAll(p => p.experation <= 0); } private void SpawnSplash(Vector3 worlPoint) { //TODO: implament spawning of your splash effect e.g. the visual effect of a projectile hitting something } } public class ProjectileData { public Vector3 pos; public Quaternion rot; public Vector3 scale; public float experation; public int team; public float damage; public float damageScale; public Matrix4x4 renderData { get { return Matrix4x4.TRS(pos, rot, scale); } } }

Viewing all articles
Browse latest Browse all 102

Trending Articles



<script src="https://jsc.adskeeper.com/r/s/rssing.com.1596347.js" async> </script>