unity-fracture
unity-fracture copied to clipboard
Any way to remove chunks rather than send chunks flying?
Thank you for publishing this awesome project.
I'm trying to use this to remove chunks instead of blast them away. So, I modified the ChunkNode.cs script to try to Destroy the pieces when they're clicked (added void OnMouseDown, for example) but this caused problems with the script still trying to access Rigidbodies. I also tried to add logic like "if (rb)" instead of running Rigidbody-accessing codeblocks by default.
I'm not that comfortable with C#, honestly, so I was wondering if anyone could take a look and let me know the correct way to modify this script's behavior to simply remove Mouse-clicked chunks, rather than blast them flying away?
My poorly changed code:
using System.Collections.Generic;
using System.Linq;
using Project.Scripts.Utils;
using UnityEngine;
namespace Project.Scripts.Fractures
{
public class ChunkNode : MonoBehaviour
{
public HashSet<ChunkNode> Neighbours = new HashSet<ChunkNode>();
public ChunkNode[] NeighboursArray = new ChunkNode[0];
private Dictionary<Joint, ChunkNode> JointToChunk = new Dictionary<Joint, ChunkNode>();
private Dictionary<ChunkNode, Joint> ChunkToJoint = new Dictionary<ChunkNode, Joint>();
private Rigidbody rb;
private Vector3 frozenPos;
private Quaternion forzenRot;
private bool frozen;
public bool IsStatic => rb.isKinematic;
public Color Color { get; set; } = Color.black;
public bool HasBrokenLinks { get; private set; }
void OnMouseDown()
{
Destroy(this.gameObject);
return;
}
private bool Contains(ChunkNode chunkNode)
{
return Neighbours.Contains(chunkNode);
}
private void FixedUpdate()
{
// Kinda hacky, but otherwise the chunks slowly drift apart.
if (frozen)
{
transform.position = frozenPos;
transform.rotation = forzenRot;
}
}
public void Setup()
{
rb = GetComponent<Rigidbody>();
Freeze();
JointToChunk.Clear();
ChunkToJoint.Clear();
foreach (var joint in GetComponents<Joint>())
{
var chunk = joint.connectedBody.GetOrAddComponent<ChunkNode>();
JointToChunk[joint] = chunk;
ChunkToJoint[chunk] = joint;
}
foreach (var chunkNode in ChunkToJoint.Keys)
{
Neighbours.Add(chunkNode);
if (chunkNode.Contains(this) == false)
{
chunkNode.Neighbours.Add(this);
}
}
NeighboursArray = Neighbours.ToArray();
}
private void OnJointBreak(float breakForce)
{
HasBrokenLinks = true;
}
public void CleanBrokenLinks()
{
var brokenLinks = JointToChunk.Keys.Where(j => j == false).ToList();
foreach (var link in brokenLinks)
{
var body = JointToChunk[link];
JointToChunk.Remove(link);
ChunkToJoint.Remove(body);
body.Remove(this);
Neighbours.Remove(body);
}
NeighboursArray = Neighbours.ToArray();
HasBrokenLinks = false;
}
private void Remove(ChunkNode chunkNode)
{
ChunkToJoint.Remove(chunkNode);
Neighbours.Remove(chunkNode);
NeighboursArray = Neighbours.ToArray();
}
public void Unfreeze()
{
frozen = false;
rb.constraints = RigidbodyConstraints.None;
rb.useGravity = true;
rb.gameObject.layer = LayerMask.NameToLayer("Default");
}
private void Freeze()
{
frozen = true;
rb.constraints = RigidbodyConstraints.FreezeAll;
rb.useGravity = false;
rb.gameObject.layer = LayerMask.NameToLayer("FrozenChunks");
frozenPos = rb.transform.position;
forzenRot = rb.transform.rotation;
}
private void OnDrawGizmos()
{
Gizmos.color = Color;
Gizmos.DrawSphere(transform.TransformPoint(transform.GetComponent<Rigidbody>().centerOfMass), 0.1f);
foreach (var joint in JointToChunk.Keys)
{
if (joint)
{
if (rb)
{
var from = transform.TransformPoint(rb.centerOfMass);
if (joint.connectedBody)
{
var to = joint.connectedBody.transform.TransformPoint(joint.connectedBody.centerOfMass);
Gizmos.DrawLine(from, to);
}
}
}
}
}
private void OnDrawGizmosSelected()
{
foreach (var node in Neighbours)
{
var mesh = node.GetComponent<MeshFilter>().mesh;
Gizmos.color = Color.yellow.SetAlpha(.2f);
Gizmos.DrawMesh(mesh, node.transform.position, node.transform.rotation);
}
}
}
}