Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- //=====================================================================================
- // Author: Stephen Spanner
- // Class : Debris
- // Desc : Used in the debris chunks of shattered the shattered unity models. These
- // pieces of debris would know of neighbour information, the surface coverage
- // they share, which could notify neighbours either beside or above them to
- // trigger to fall (causing chain reactions)
- //=====================================================================================
- using UnityEngine;
- using System.Collections.Generic;
- // ------------------------------------------------------------------------------------
- public class Debris : MonoBehaviour
- {
- // ------------- CONSTANTS ----------------
- private const float UNSUPPORTED_WEIGHT = 1.0f;
- private const float SUPPORTED_WEIGHT = 5.0f;
- private const float SUPPORT_BROKEN_THRESHOLD = 0.5f;
- // Serializable, so we can read the information of neighbours within the inspector.
- [System.Serializable]
- public class DebrisInfo
- {
- // Constructor
- public DebrisInfo(
- Debris n,
- float s)
- {
- neighbourDebris = n;
- surfaceSpace = s;
- }
- public Debris neighbourDebris; // The neighbour Debris
- public float surfaceSpace; // a percentage (weight) of surface space
- // shared with all other neighbours
- }
- public List<DebrisInfo> mDebrisList; // A list of all neighbour debris
- private Rigidbody mRigidBody; // The rigidbody of the debris object
- // ------------- ACCESSORS -----------------
- public bool IsKinematic
- {
- get { return mRigidBody.isKinematic; }
- }
- public float YPos
- {
- get { return transform.position.y; }
- }
- //---------------------------------------------------------------
- // Start()
- // Sets up necessary variables and the rigidbody and cleans up
- // if any mistakes exist
- //---------------------------------------------------------------
- void Start()
- {
- mDebrisList = new List<DebrisInfo>();
- mRigidBody = GetComponent<Rigidbody>();
- // If Rigidbody doesn't exist on Debris object
- if( !mRigidBody )
- {
- Debug.LogError( "[Debris] ERROR: Debris is missing RigidBody. Removing!" );
- Destroy( gameObject );
- }
- }
- //---------------------------------------------------------------
- // RepopulateNeighbours()
- // Clears the debris list and recreates it. (Called from the parent object)
- //---------------------------------------------------------------
- public void RepopulateNeighbours( List<DebrisInfo> debris )
- {
- mDebrisList.Clear();
- // Add each new debris into the empty list
- foreach( DebrisInfo info in debris)
- {
- mDebrisList.Add( info );
- }
- }
- //---------------------------------------------------------------
- // CheckForNeighbourAbsence()
- // Looks through the neighbour debris to see if that all of the links
- // are missing, or if the amount of neighbours that have already been
- // disrupted exceeds a certain threshold.
- //---------------------------------------------------------------
- private List<Debris> CheckForNeighbourAbsence()
- {
- // We want to see if our rigidbody is not kinematic, if so
- // then we return a blank neighbour list and go no further.
- List<Debris> newDebris = new List<Debris>();
- if ( !IsKinematic )
- return newDebris;
- // Make sure the Debris List exists and is populated
- if( mDebrisList != null && mDebrisList.Count() > 0 )
- {
- int brokenLinks = 0;
- float totalSurfaceAmount = 0.01f;
- float remaindingSurfaceAmount = 0.0f;
- for( int i = 0; i < mDebrisList.Count; i++ )
- {
- // Possibly the debris may have despawned or been destroyed
- // through other means
- if( mDebrisList[ i ].neighbourDebris == null )
- {
- brokenLinks++;
- continue;
- }
- // Grab the rigidbody of the checked neighbour.
- Rigidbody rigidBody = mDebrisList[ i ].neighbourDebris.GetComponent<Rigidbody>();
- // Neighbours that are either besides or above this debris will only have a lesser
- // weight applied to them. However ones that are below them count as supporting, and
- // will account for more of their surface weight.
- float modifier = UNSUPPORTED_WEIGHT;
- if ( mDebrisList[ i ].neighbourDebris.YPos < YPos )
- modifier = SUPPORTED_WEIGHT;
- // Increase total surface amount
- totalSurfaceAmount += ( mDebrisList[ i ].surfaceSpace * modifier );
- // Break links to neighbours that are already non-kinematic
- if ( !mDebrisList[ i ].neighbourDebris.IsKinematic )
- brokenLinks++;
- else
- remaindingSurfaceAmount += mDebrisList[ i ].surfaceSpace * modifier;
- }
- // If all links to neighbours are broken, or the surface space is less than the support broken threshold
- // then we set the rigidobdy to non-kinematic.
- if( brokenLinks >= mDebrisList.Count || ( remaindingSurfaceAmount / totalSurfaceAmount ) < SUPPORT_BROKEN_THRESHOLD )
- {
- mRigidBody.isKinematic = false;
- // We then populate the newDebris list with all the available and kinematic neighbours and return it.
- for ( int i = 0; i < mDebrisList.Count; i++ )
- {
- if ( mDebrisList[ i ].neighbourDebris != null && mDebrisList[ i ].neighbourDebris.IsKinematic )
- newDebris.Add( mDebrisList[ i ].neighbourDebris );
- }
- }
- }
- return newDebris;
- }
- //---------------------------------------------------------------
- // CheckNeighbours()
- // Creates an array of all the children debris of the parent object
- // and forces them to check for neighbour absence. This is useful for
- // impacting a tremendous force on the object containing debris, so
- // we can force all broken neighbour links to detatch immediately.
- //---------------------------------------------------------------
- public void CheckNeighbours()
- {
- // Grabs the array of all the parents children debris.
- Debris[] debrisList = transform.parent.gameObject.GetComponentsInChildren<Debris>();
- for ( int i = 0; i < debrisList.Length; i++ )
- {
- if ( debrisList[ i ] != null )
- {
- // For all existing kinematic debris, we'll check them.
- if ( debrisList[ i ].IsKinematic )
- debrisList[ i ].CheckForNeighbourAbsence();
- }
- }
- }
- //---------------------------------------------------------------
- // CreateList()
- // Simply creates a list of all the entities debris, neighbour or not.
- //---------------------------------------------------------------
- private List<Debris> CreateList()
- {
- // Grab all of the sibling debris from our parent.
- Debris[] allDebris = gameObject.transform.parent.GetComponentsInChildren<Debris>();
- List<Debris> debrisList = new List<Debris>();
- // Add each one of them to a list as long as they're kinematic.
- for( int i = 0; i < allDebris.Length; i++ )
- {
- if( allDebris[ i ].IsKinematic )
- debrisList.Add( allDebris[ i ] );
- }
- return debrisList;
- }
- //---------------------------------------------------------------
- // DoCollision()
- // Sets the rigidbody to non-kinematic, which will then detatch it and
- // cycle through all neighbours, seeing if it will cause a chain reaction
- // making other debris detatch and fall.
- //
- // TODO: Add damage impact and debris health
- //---------------------------------------------------------------
- public void DoCollision()
- {
- // Only if it is currently kinematic, we'll turn it off causing physics
- // to affect this object.
- if ( mRigidBody.isKinematic )
- {
- mRigidBody.isKinematic = false;
- // Grab a list of ALL the sibling debris.
- List<Debris> debrisList = CreateList();
- // Check each debris, to see if it's neighbours are absent, or not enough
- // structure will hold it up.
- while( debrisList.Count > 0 )
- {
- if ( debrisList[ 0 ].IsKinematic )
- {
- // Check for lack of support.
- List<Debris> newDebris = debrisList[ 0 ].CheckForNeighbourAbsence();
- for ( int i = 0; i < newDebris.Count; i++ )
- {
- // For each NON-listed debris in our main array, we want to add
- // any new affected debris to be re-checked, in case they can cause
- // a chain reaction to already-checked objects.
- if ( !debrisList.Contains( newDebris[ i ] ) )
- debrisList.Add( newDebris[ i ] );
- }
- }
- debrisList.RemoveAt( 0 );
- }
- }
- // After the collision from the object, and we've done all the neighbour checks, we want
- // to remove the Debris component from this object to greatly improve performance and
- // reduced checks from its siblings.
- Destroy( this );
- }
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement