Advertisement
Guest User

Debris.cs

a guest
Jan 11th, 2017
158
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C# 8.45 KB | None | 0 0
  1. //=====================================================================================
  2. // Author: Stephen Spanner
  3. // Class : Debris
  4. // Desc  : Used in the debris chunks of shattered the shattered unity models. These
  5. //         pieces of debris would know of neighbour information, the surface coverage
  6. //         they share, which could notify neighbours either beside or above them to
  7. //         trigger to fall (causing chain reactions)
  8. //=====================================================================================
  9.  
  10. using UnityEngine;
  11. using System.Collections.Generic;
  12.  
  13. // ------------------------------------------------------------------------------------
  14. public class Debris : MonoBehaviour
  15. {
  16.     // ------------- CONSTANTS ----------------
  17.     private const float UNSUPPORTED_WEIGHT = 1.0f;
  18.     private const float SUPPORTED_WEIGHT = 5.0f;
  19.     private const float SUPPORT_BROKEN_THRESHOLD = 0.5f;
  20.  
  21.     // Serializable, so we can read the information of neighbours within the inspector.
  22.     [System.Serializable]
  23.     public class DebrisInfo
  24.     {
  25.         // Constructor
  26.         public DebrisInfo(
  27.             Debris n,
  28.             float s)
  29.         {
  30.             neighbourDebris = n;
  31.             surfaceSpace = s;
  32.         }
  33.  
  34.         public Debris neighbourDebris;      // The neighbour Debris
  35.         public float surfaceSpace;          // a percentage (weight) of surface space
  36.                                             // shared with all other neighbours
  37.     }
  38.    
  39.     public List<DebrisInfo> mDebrisList;    // A list of all neighbour debris
  40.     private Rigidbody mRigidBody;           // The rigidbody of the debris object
  41.  
  42.     // ------------- ACCESSORS -----------------
  43.     public bool IsKinematic
  44.     {
  45.         get { return mRigidBody.isKinematic; }
  46.     }
  47.  
  48.     public float YPos
  49.     {
  50.         get { return transform.position.y; }
  51.     }
  52.  
  53.     //---------------------------------------------------------------
  54.     // Start()
  55.     // Sets up necessary variables and the rigidbody and cleans up
  56.     // if any mistakes exist
  57.     //---------------------------------------------------------------
  58.     void Start()
  59.     {
  60.         mDebrisList = new List<DebrisInfo>();
  61.         mRigidBody = GetComponent<Rigidbody>();
  62.  
  63.         // If Rigidbody doesn't exist on Debris object
  64.         if( !mRigidBody )
  65.         {
  66.             Debug.LogError( "[Debris] ERROR: Debris is missing RigidBody. Removing!" );
  67.             Destroy( gameObject );
  68.         }
  69.     }
  70.  
  71.     //---------------------------------------------------------------
  72.     // RepopulateNeighbours()
  73.     // Clears the debris list and recreates it. (Called from the parent object)
  74.     //---------------------------------------------------------------
  75.     public void RepopulateNeighbours( List<DebrisInfo> debris )
  76.     {
  77.         mDebrisList.Clear();
  78.  
  79.         // Add each new debris into the empty list
  80.         foreach( DebrisInfo info in debris)
  81.         {
  82.             mDebrisList.Add( info );
  83.         }
  84.     }
  85.  
  86.     //---------------------------------------------------------------
  87.     // CheckForNeighbourAbsence()
  88.     // Looks through the neighbour debris to see if that all of the links
  89.     // are missing, or if the amount of neighbours that have already been
  90.     // disrupted exceeds a certain threshold.
  91.     //---------------------------------------------------------------
  92.     private List<Debris> CheckForNeighbourAbsence()
  93.     {
  94.         // We want to see if our rigidbody is not kinematic, if so
  95.         // then we return a blank neighbour list and go no further.
  96.         List<Debris> newDebris = new List<Debris>();
  97.         if ( !IsKinematic )
  98.             return newDebris;
  99.  
  100.         // Make sure the Debris List exists and is populated
  101.         if( mDebrisList != null && mDebrisList.Count() > 0 )
  102.         {
  103.             int brokenLinks = 0;
  104.  
  105.             float totalSurfaceAmount = 0.01f;
  106.             float remaindingSurfaceAmount = 0.0f;
  107.            
  108.             for( int i = 0; i < mDebrisList.Count; i++ )
  109.             {
  110.                 // Possibly the debris may have despawned or been destroyed
  111.                 // through other means
  112.                 if( mDebrisList[ i ].neighbourDebris == null )
  113.                 {
  114.                     brokenLinks++;
  115.                     continue;
  116.                 }
  117.  
  118.                 // Grab the rigidbody of the checked neighbour.
  119.                 Rigidbody rigidBody = mDebrisList[ i ].neighbourDebris.GetComponent<Rigidbody>();
  120.  
  121.                 // Neighbours that are either besides or above this debris will only have a lesser
  122.                 // weight applied to them. However ones that are below them count as supporting, and
  123.                 // will account for more of their surface weight.
  124.                 float modifier = UNSUPPORTED_WEIGHT;
  125.                 if ( mDebrisList[ i ].neighbourDebris.YPos < YPos )
  126.                     modifier = SUPPORTED_WEIGHT;
  127.  
  128.                 // Increase total surface amount
  129.                 totalSurfaceAmount += ( mDebrisList[ i ].surfaceSpace * modifier );
  130.  
  131.                 // Break links to neighbours that are already non-kinematic
  132.                 if ( !mDebrisList[ i ].neighbourDebris.IsKinematic )
  133.                     brokenLinks++;
  134.                 else
  135.                     remaindingSurfaceAmount += mDebrisList[ i ].surfaceSpace * modifier;
  136.             }
  137.  
  138.             // If all links to neighbours are broken, or the surface space is less than the support broken threshold
  139.             // then we set the rigidobdy to non-kinematic.
  140.             if( brokenLinks >= mDebrisList.Count || ( remaindingSurfaceAmount / totalSurfaceAmount ) < SUPPORT_BROKEN_THRESHOLD )
  141.             {
  142.                 mRigidBody.isKinematic = false;
  143.  
  144.                 // We then populate the newDebris list with all the available and kinematic neighbours and return it.
  145.                 for ( int i = 0; i < mDebrisList.Count; i++ )
  146.                 {
  147.                     if ( mDebrisList[ i ].neighbourDebris != null && mDebrisList[ i ].neighbourDebris.IsKinematic )
  148.                         newDebris.Add( mDebrisList[ i ].neighbourDebris );
  149.                 }
  150.             }
  151.         }
  152.         return newDebris;
  153.     }
  154.  
  155.  
  156.     //---------------------------------------------------------------
  157.     // CheckNeighbours()
  158.     // Creates an array of all the children debris of the parent object
  159.     // and forces them to check for neighbour absence. This is useful for
  160.     // impacting a tremendous force on the object containing debris, so
  161.     // we can force all broken neighbour links to detatch immediately.
  162.     //---------------------------------------------------------------
  163.     public void CheckNeighbours()
  164.     {
  165.         // Grabs the array of all the parents children debris.
  166.         Debris[] debrisList = transform.parent.gameObject.GetComponentsInChildren<Debris>();
  167.  
  168.         for ( int i = 0; i < debrisList.Length; i++ )
  169.         {
  170.             if ( debrisList[ i ] != null )
  171.             {
  172.                 // For all existing kinematic debris, we'll check them.
  173.                 if ( debrisList[ i ].IsKinematic )
  174.                     debrisList[ i ].CheckForNeighbourAbsence();
  175.             }
  176.         }
  177.     }
  178.  
  179.     //---------------------------------------------------------------
  180.     // CreateList()
  181.     // Simply creates a list of all the entities debris, neighbour or not.
  182.     //---------------------------------------------------------------
  183.     private List<Debris> CreateList()
  184.     {
  185.         // Grab all of the sibling debris from our parent.
  186.         Debris[] allDebris = gameObject.transform.parent.GetComponentsInChildren<Debris>();
  187.         List<Debris> debrisList = new List<Debris>();
  188.  
  189.         // Add each one of them to a list as long as they're kinematic.
  190.         for( int i = 0; i < allDebris.Length; i++ )
  191.         {
  192.             if( allDebris[ i ].IsKinematic )
  193.                 debrisList.Add( allDebris[ i ] );
  194.         }
  195.  
  196.         return debrisList;
  197.     }
  198.  
  199.     //---------------------------------------------------------------
  200.     // DoCollision()
  201.     // Sets the rigidbody to non-kinematic, which will then detatch it and
  202.     // cycle through all neighbours, seeing if it will cause a chain reaction
  203.     // making other debris detatch and fall.
  204.     //
  205.     // TODO: Add damage impact and debris health
  206.     //---------------------------------------------------------------
  207.     public void DoCollision()
  208.     {
  209.         // Only if it is currently kinematic, we'll turn it off causing physics
  210.         // to affect this object.
  211.         if ( mRigidBody.isKinematic )
  212.         {
  213.             mRigidBody.isKinematic = false;
  214.  
  215.             // Grab a list of ALL the sibling debris.
  216.             List<Debris> debrisList = CreateList();
  217.            
  218.             // Check each debris, to see if it's neighbours are absent, or not enough
  219.             // structure will hold it up.
  220.             while( debrisList.Count > 0 )
  221.             {
  222.                 if ( debrisList[ 0 ].IsKinematic )
  223.                 {
  224.                     // Check for lack of support.
  225.                     List<Debris> newDebris = debrisList[ 0 ].CheckForNeighbourAbsence();
  226.                     for ( int i = 0; i < newDebris.Count; i++ )
  227.                     {
  228.                         // For each NON-listed debris in our main array, we want to add
  229.                         // any new affected debris to be re-checked, in case they can cause
  230.                         // a chain reaction to already-checked objects.
  231.                         if ( !debrisList.Contains( newDebris[ i ] ) )
  232.                             debrisList.Add( newDebris[ i ] );
  233.                     }
  234.                 }
  235.                 debrisList.RemoveAt( 0 );
  236.             }
  237.         }
  238.  
  239.         // After the collision from the object, and we've done all the neighbour checks, we want
  240.         // to remove the Debris component from this object to greatly improve performance and
  241.         // reduced checks from its siblings.
  242.         Destroy( this );
  243.     }
  244. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement