RopeBuilder.cs 3.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112
  1. using SplineMesh;
  2. using System.Collections;
  3. using System.Collections.Generic;
  4. using System.Linq;
  5. using UnityEngine;
  6. namespace SplineMesh {
  7. [ExecuteInEditMode]
  8. [RequireComponent(typeof(Spline))]
  9. public class RopeBuilder : MonoBehaviour {
  10. private bool toUpdate = false;
  11. private GameObject generated;
  12. private GameObject Generated {
  13. get {
  14. if (generated == null) {
  15. string generatedName = "generated by " + GetType().Name;
  16. var generatedTranform = transform.Find(generatedName);
  17. generated = generatedTranform != null ? generatedTranform.gameObject : UOUtility.Create(generatedName, gameObject);
  18. }
  19. return generated;
  20. }
  21. }
  22. private Spline spline;
  23. private GameObject firstSegment;
  24. [SerializeField]
  25. public List<GameObject> wayPoints = new List<GameObject>();
  26. public GameObject segmentPrefab;
  27. public int segmentCount;
  28. public float segmentSpacing;
  29. private void OnEnable() {
  30. spline = GetComponent<Spline>();
  31. toUpdate = true;
  32. }
  33. private void OnValidate() {
  34. toUpdate = true;
  35. }
  36. private void Update() {
  37. if (toUpdate) {
  38. toUpdate = false;
  39. Generate();
  40. UpdateSpline();
  41. }
  42. UpdateNodes();
  43. // balancing
  44. if (Application.isPlaying) {
  45. firstSegment.transform.localPosition = new Vector3(Mathf.Sin(Time.time) * 3, 0, 0);
  46. }
  47. }
  48. private void UpdateNodes() {
  49. int i = 0;
  50. foreach (GameObject wayPoint in wayPoints) {
  51. var node = spline.nodes[i++];
  52. if (Vector3.Distance(node.Position, transform.InverseTransformPoint(wayPoint.transform.position)) > 0.001f) {
  53. node.Position = transform.InverseTransformPoint(wayPoint.transform.position);
  54. node.Up = wayPoint.transform.up;
  55. }
  56. }
  57. }
  58. private void UpdateSpline() {
  59. foreach (var penisNode in wayPoints.ToList()) {
  60. if (penisNode == null) wayPoints.Remove(penisNode);
  61. }
  62. int nodeCount = wayPoints.Count;
  63. // adjust the number of nodes in the spline.
  64. while (spline.nodes.Count < nodeCount) {
  65. spline.AddNode(new SplineNode(Vector3.zero, Vector3.zero));
  66. }
  67. while (spline.nodes.Count > nodeCount && spline.nodes.Count > 2) {
  68. spline.RemoveNode(spline.nodes.Last());
  69. }
  70. }
  71. private void Generate() {
  72. UOUtility.DestroyChildren(Generated);
  73. wayPoints.Clear();
  74. float localSpacing = 0;
  75. Joint joint = null;
  76. for (int i = 0; i < segmentCount; i++) {
  77. var seg = UOUtility.Instantiate(segmentPrefab, Generated.transform);
  78. seg.transform.Translate(0, 0, localSpacing);
  79. var segRB = seg.GetComponent<Rigidbody>();
  80. // we fix the first segment so that the rope won't fall
  81. if (i == 0) {
  82. firstSegment = seg;
  83. segRB.constraints = RigidbodyConstraints.FreezePosition;
  84. }
  85. // we attach the rigidbody to the joint of the previous segment
  86. if (joint != null) {
  87. joint.connectedBody = segRB;
  88. }
  89. joint = seg.GetComponent<Joint>();
  90. // we save segments as way points for the spline deformation.
  91. wayPoints.Add(seg);
  92. localSpacing += segmentSpacing;
  93. }
  94. UOUtility.Destroy(joint);
  95. }
  96. }
  97. }