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);
}
}
}
}
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: