using System.Collections; using System.Collections.Generic; using UnityEngine; namespace Obi { /** * This component plugs a prefab instance at each cut in the rope. Optionally, it will also place a couple instances at the start/end of an open rope. */ [RequireComponent(typeof(ObiPathSmoother))] public class ObiRopePrefabPlugger : MonoBehaviour { public GameObject prefab; /**< prefab object being instantiated at the rope cuts.*/ public Vector3 instanceScale = Vector3.one; public bool plugTears = true; public bool plugStart = false; public bool plugEnd = false; private List instances; /**< instances of the prefab being rendered. */ private ObiPathSmoother smoother; void OnEnable() { instances = new List(); smoother = GetComponent(); GetComponent().OnInterpolate += UpdatePlugs; } void OnDisable() { GetComponent().OnInterpolate -= UpdatePlugs; ClearPrefabInstances(); } private GameObject GetOrCreatePrefabInstance(int index) { if (index < instances.Count) return instances[index]; GameObject tearPrefabInstance = Instantiate(prefab); tearPrefabInstance.hideFlags = HideFlags.HideAndDontSave; instances.Add(tearPrefabInstance); return tearPrefabInstance; } public void ClearPrefabInstances() { for (int i = 0; i < instances.Count; ++i) DestroyImmediate(instances[i]); instances.Clear(); } // Update is called once per frame void UpdatePlugs(ObiActor actor, float simulatedTime, float substepTime) { if (!actor.isLoaded) return; // cache the rope's transform matrix/quaternion: Matrix4x4 l2w = smoother.actor.solver.transform.localToWorldMatrix; Quaternion l2wRot = l2w.rotation; int instanceIndex = 0; var system = actor.solver.GetRenderSystem() as ObiPathSmootherRenderSystem; int chunkCount = system.GetChunkCount(smoother.indexInSystem); // place prefabs at the start/end of each curve: for (int c = 0; c < chunkCount; ++c) { if ((plugTears && c > 0) || (plugStart && c == 0)) { var instance = GetOrCreatePrefabInstance(instanceIndex++); instance.SetActive(true); ObiPathFrame frame = system.GetFrameAt(smoother.indexInSystem, c, 0); instance.transform.position = l2w.MultiplyPoint3x4(frame.position); instance.transform.rotation = l2wRot * (Quaternion.LookRotation(-frame.tangent, frame.binormal)); instance.transform.localScale = instanceScale; } if ((plugTears && c < chunkCount - 1) || (plugEnd && c == chunkCount - 1)) { var instance = GetOrCreatePrefabInstance(instanceIndex++); instance.SetActive(true); int frameCount = system.GetSmoothFrameCount(smoother.indexInSystem, c); ObiPathFrame frame = system.GetFrameAt(smoother.indexInSystem, c, frameCount-1); instance.transform.position = l2w.MultiplyPoint3x4(frame.position); instance.transform.rotation = l2wRot * Quaternion.LookRotation(frame.tangent, frame.binormal); instance.transform.localScale = instanceScale; } } // deactivate remaining instances: for (int i = instanceIndex; i < instances.Count; ++i) instances[i].SetActive(false); } } }