I think I found the solution.
I use this piece of code for offsetting between characters.
Code:
[Section("Lane", Sort = 0)]
[SerializeField] private float _offset = 5f;
/// <summary>
/// This is called just after the SplineController has been initialized
/// </summary>
protected override void UserAfterInit()
{
SetOffset();
}
/// <summary>
/// This is called just after the SplineController updates
/// </summary>
protected override void UserAfterUpdate()
{
SetOffset();
}
void SetOffset()
{
if (Spline.Dirty)
Spline.Refresh();
transform.Translate(_offset, 0, 0, Space.Self);
}
Is it correct ? Or there is a better way to do so ? Any way to consider separate path for each lane ?
Or is it possible to generate meshes a curvy spline path and then generate separate splines for 4 lanes ?
Look at this image:
https://gyazo.com/206d782ecc94c9d68ef3bf929bac66d9
As you see 4 parallel lanes are changed to 2 pairs. I want 2 separate splines for right one and 2 for left one and connection between 4 lanes to 2 pairs of 2 lanes. You know what I mean ?
[Edit]
I wrote these codes for lane changing and spline switching at connection. Do you think it is a good approach or there is a better one ?
This one attached to the character:
Code:
public class CharacterController : SplineController
{
[Section("Lane", Sort = 0)]
[SerializeField] private float _offset = 5f;
[SerializeField] private float _changeingLaneTime = 0.5f;
private float _targetOffset;
private IEnumerator _lerpOffset;
private int _minOffset;
private int _maxOffset;
/// <summary>
/// This is called just after the SplineController has been initialized
/// </summary>
protected override void UserAfterInit()
{
_targetOffset = _offset;
_minOffset = -3;
_maxOffset = 3;
SetOffset();
}
/// <summary>
/// This is called just after the SplineController updates
/// </summary>
protected override void UserAfterUpdate()
{
ChangeLane();
SetOffset();
}
void SetOffset()
{
if (Spline.Dirty)
Spline.Refresh();
transform.Translate(_offset, 0, 0, Space.Self);
}
private void ChangeLane()
{
if (Input.GetKeyDown(KeyCode.RightArrow))
{
_targetOffset = Mathf.Clamp(_targetOffset + 2, _minOffset, _maxOffset);
StartLerpingOffset(_targetOffset);
}
if (Input.GetKeyDown(KeyCode.LeftArrow))
{
_targetOffset = Mathf.Clamp(_targetOffset - 2, _minOffset, _maxOffset);
StartLerpingOffset(_targetOffset);
}
}
private void StartLerpingOffset(float amount)
{
if (_lerpOffset != null)
{
StopCoroutine(_lerpOffset);
}
_lerpOffset = LerpOffset(_offset, amount);
StartCoroutine(_lerpOffset);
}
IEnumerator LerpOffset(float current, float target)
{
float currentTime = 0;
float perc = 0;
while (perc != 1)
{
currentTime += Time.deltaTime;
if (currentTime > _changeingLaneTime)
{
currentTime = _changeingLaneTime;
}
perc = currentTime / _changeingLaneTime;
_offset = Mathf.Lerp(current, target, perc);
yield return null;
}
}
private void ChangeOffsetLimit(int[] offsets)
{
_minOffset = Mathf.Min(offsets);
_maxOffset = Mathf.Max(offsets);
}
private void ControlTracks(CurvySplineMoveEventArgs e)
{
ControlPointMetaData cpMetaData = e.ControlPoint.GetComponent<ControlPointMetaData>();
if (cpMetaData != null && Array.Exists(cpMetaData.supportingOffsets, _ => _ == _targetOffset))
{
ChangeOffsetLimit(cpMetaData.supportingOffsets);
return;
}
if (e.ControlPoint.Connection == null)
{
return;
}
for (int i = 0; i < e.ControlPoint.Connection.ControlPointsList.Count; i++)
{
CurvySplineSegment currentControlPoint = e.ControlPoint.Connection.ControlPointsList[i];
ControlPointMetaData currenCPMetaData = currentControlPoint.GetComponent<ControlPointMetaData>();
if (currenCPMetaData != null && Array.Exists(currenCPMetaData.supportingOffsets, _ => _ == _targetOffset))
{
Vector3 lookupPos = Spline.transform.InverseTransformPoint(transform.position);
float nearestPointTF = currentControlPoint.Spline.GetNearestPointTF(lookupPos);
Spline = currentControlPoint.Spline;
Position = nearestPointTF;
ChangeOffsetLimit(currenCPMetaData.supportingOffsets);
break;
}
}
}
public void OnCPReached(CurvySplineMoveEventArgs e)
{
ControlTracks(e);
}
}
This one attached to the control points which has connections:
Code:
public class ControlPointMetaData : MonoBehaviour
{
public int[] supportingOffsets;
}