我正在尝试使用https://unitylist.com/p/l7c/Destructible-Walls
中一个非常好的项目它使用Nvidia Blast创建可破坏对象。因为我使用它来删除块而不是爆炸它们,所以我修改了ChunkNode.cs
脚本以尝试在单击它们时销毁它们(请参阅OnMouseDown
),但这导致了有关该脚本的许多错误仍在尝试访问刚体。
我对脚本进行了一些修改,以尝试用if (rb)
之类的方式解决这个问题,但是仍然不满意。任何人都可以看一下,并让我知道修改此脚本行为的正确方法,以简单地删除鼠标单击的块,而不是炸开它们吗?
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);
}
}
}
}