void Update() { timeSinceLastShake += Time.deltaTime; // Is it time for a new shake? if (timeSinceLastShake > currentShakeGap) { // Iterate through all the control points for (int index = 0; index < rageSpline.GetPointCount(); index++) { // Randomise a new shake vector Vector3 shakeVector = new Vector3( Random.Range(-0.5f * shakeSizeInNormalSpace.x, 0.5f * shakeSizeInNormalSpace.x), Random.Range(-0.5f * shakeSizeInNormalSpace.y, 0.5f * shakeSizeInNormalSpace.y), 0f); // Get normal and tangent for the control point. We will shake along the normal. Vector3 normal = rageSpline.GetNormal(index); Vector3 tangent = Vector3.Cross(normal, Camera.main.transform.forward); // Set a new position for the control point targetPositions[index] = originalPositions[index] + shakeVector.x * tangent + shakeVector.y * normal; } // When is the next new shake? currentShakeGap = Random.Range(minFrameGap, maxFrameGap); timeSinceLastShake = 0f; } else { // Iterate through all the control points for (int index = 0; index < rageSpline.GetPointCount(); index++) { // Interpolate toward Target positions with Vector3.Lerp() Vector3 currentPosition = rageSpline.GetPosition(index); rageSpline.SetPoint(index, Vector3.Lerp(currentPosition, targetPositions[index], Time.deltaTime * (1f / easing))); } } // Finally refresh the visible mesh rageSpline.RefreshMesh(true, true, false); // Faster version (possible artifacts) //rageSpline.RefreshMesh(false, false, false); }