예제 #1
0
        public void ExecuteExplosions(IEnumerable <Explosion> explosions, IEnumerable <DestructibleObject> dtObjects, IPolygonSubtractor subtractor)
        {
            // Store destructible objects in a new list, since we may add or remove some during processing
            List <DestructibleObject> dtObjectList = dtObjects.ToList();
            // Add new destructible objects to this list instead of objectList until finished processing the current explosion
            List <DestructibleObject> pendingAdditions = new List <DestructibleObject>();

            // Process all objects for all explosions
            foreach (var exp in explosions)
            {
                List <List <DTPolygon> > relevantObjectPolygons = new List <List <DTPolygon> >();
                List <int> relevantObjectIndices = new List <int>();
                for (int i = 0; i < dtObjectList.Count; ++i)
                {
                    var dtObj = dtObjectList[i];

                    // Do basic AABB-circle check to see whether we can skip processing this destructible object with this explosion
                    int bc = DTUtility.BoundsCheck(dtObj, exp);
                    if (bc == -1)
                    {
                        // Object is not affected by explosion
                        continue;
                    }
                    else if (bc == 1)
                    {
                        // Object is completely removed by explosion
                        dtObjectList[i] = null;
                        UnityEngine.Object.Destroy(dtObj.gameObject);
                        continue;
                    }
                    else
                    {
                        // Add object to the input list for the subtractor
                        relevantObjectPolygons.Add(dtObj.GetTransformedPolygonList());
                        relevantObjectIndices.Add(i);
                        continue;
                    }
                }

                var result = subtractor.SubtractBulk(relevantObjectPolygons, new DTPolygon[] { exp.DTPolygon });

                // Iterate results corresponding to each input polygon group
                for (int i = 0; i < result.Count; i++)
                {
                    // Add new destructible objects for any output polygons that could not be matched with an input polygon
                    if (i >= relevantObjectPolygons.Count)
                    {
                        GameObject         go        = new GameObject();
                        DestructibleObject newObj    = go.AddComponent <DestructibleObject>();
                        List <DTPolygon>   polygroup = result[i][0];
                        newObj.ApplyTransformedPolygonList(polygroup);
                        pendingAdditions.Add(newObj);

                        continue;
                    }

                    // We know that these output polygons correspond to one or more pieces of this existing destructible object
                    DestructibleObject dtObj = dtObjectList[relevantObjectIndices[i]];

                    if (result[i].Count == 0)
                    {
                        // If no output polygons, remove the current destrucible object
                        dtObjectList[relevantObjectIndices[i]] = null;
                        UnityEngine.Object.Destroy(dtObj.gameObject);
                        continue;
                    }
                    else
                    {
                        // Otherwise apply the output polygons (fragments) to GameObjects (new or reused)
                        foreach (List <DTPolygon> polygroup in result[i])
                        {
                            if (polygroup != result[i].Last())
                            {
                                // Duplicate the GameObject that was clipped by the explosion, so that we maintain properties such as velocity
                                GameObject         go     = UnityEngine.Object.Instantiate(dtObj.gameObject, dtObj.transform.parent);
                                DestructibleObject newObj = go.GetComponent <DestructibleObject>();

                                // Apply the new clipped polygon
                                newObj.ApplyTransformedPolygonList(polygroup);

                                // Add it to the objectList, but not until after finished processing this explosion
                                pendingAdditions.Add(newObj);
                                continue;
                            }
                            else
                            {
                                // Reuse the existing GameObject by applying the new clipped polygon to it
                                dtObj.ApplyTransformedPolygonList(polygroup);
                                continue;
                            }
                        }
                    }
                }

                // Delete any entries that were set to null
                for (int i = 0; i < dtObjectList.Count; ++i)
                {
                    if (dtObjectList[i] == null)
                    {
                        dtObjectList.RemoveAt(i--);
                    }
                }

                // Add pendingAdditions elements to objectList so that they are included when processing the next explosion in explosions
                dtObjectList.AddRange(pendingAdditions);
                pendingAdditions.Clear();
            }
        }
        public void ExecuteExplosions(IEnumerable <Explosion> explosions, IEnumerable <DestructibleObject> dtObjects, IPolygonSubtractor subtractor)
        {
            // Store destructible objects in a new list, since we may add or remove some during processing
            List <DestructibleObject> dtObjectList = dtObjects.ToList();
            // Add new destructible objects to this list instead of objectList until finished processing the current explosion
            List <DestructibleObject> pendingAdditions = new List <DestructibleObject>();

            // Process all objects for all explosions
            var explosionPolygons     = explosions.Select(e => e.DTPolygon);
            var dtObjectPolygons      = dtObjectList.Select(o => o.GetTransformedPolygonList());
            int numInputPolygonGroups = dtObjectPolygons.Count();

            var result = subtractor.SubtractBulk(dtObjectPolygons, explosionPolygons);

            // Iterate results corresponding to each input polygon group
            for (int i = 0; i < result.Count; i++)
            {
                // Add new destructible objects for any output polygon groups that could not be matched with an input polygon group
                if (i >= numInputPolygonGroups)
                {
                    GameObject         go        = new GameObject();
                    DestructibleObject newObj    = go.AddComponent <DestructibleObject>();
                    List <DTPolygon>   polygroup = result[i][0];
                    newObj.ApplyTransformedPolygonList(polygroup);
                    pendingAdditions.Add(newObj);

                    continue;
                }

                // We know that these output polygons correspond to one or more pieces of this existing destructible object
                DestructibleObject dtObj = dtObjectList[i];

                if (result[i].Count == 0)
                {
                    // If no output polygons, remove the current destrucible object
                    dtObjectList[i] = null;
                    UnityEngine.Object.Destroy(dtObj.gameObject);
                    continue;
                }
                else
                {
                    // Otherwise apply the output polygons (fragments) to GameObjects (new or reused)
                    foreach (List <DTPolygon> polygroup in result[i])
                    {
                        if (polygroup != result[i].Last())
                        {
                            // Duplicate the GameObject that was clipped by the explosion, so that we maintain properties such as velocity
                            GameObject         go     = UnityEngine.Object.Instantiate(dtObj.gameObject, dtObj.transform.parent);
                            DestructibleObject newObj = go.GetComponent <DestructibleObject>();

                            // Apply the new clipped polygon
                            newObj.ApplyTransformedPolygonList(polygroup);

                            // Add it to the objectList, but not until after finished processing this explosion
                            pendingAdditions.Add(newObj);
                            continue;
                        }
                        else
                        {
                            // Reuse the existing GameObject by applying the new clipped polygon to it
                            dtObj.ApplyTransformedPolygonList(polygroup);
                            continue;
                        }
                    }
                }
            }

            // Delete any entries that were set to null
            for (int i = 0; i < dtObjectList.Count; ++i)
            {
                if (dtObjectList[i] == null)
                {
                    dtObjectList.RemoveAt(i--);
                }
            }

            // Add pendingAdditions elements to objectList so that they are included when processing the next explosion in explosions
            dtObjectList.AddRange(pendingAdditions);
            pendingAdditions.Clear();
        }