Advertisement
Staggart

Attach Transform To Spline

Apr 4th, 2024 (edited)
846
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C# 3.42 KB | None | 0 0
  1. using System;
  2. using System.Linq;
  3. using Unity.Mathematics;
  4. using UnityEngine;
  5. using UnityEngine.Splines;
  6.  
  7. namespace sc.modeling.splines.runtime.auxiliary
  8. {
  9.     //This component may be used to fix a Transform to either the start or end of a spline
  10.     [ExecuteAlways]
  11.     public class AttachTransformToSpline : MonoBehaviour
  12.     {
  13.         public SplineContainer splineContainer;
  14.  
  15.         public enum ConnectionPoint
  16.         {
  17.             Start,
  18.             End,
  19.             Custom
  20.         }
  21.         [Space]
  22.         public ConnectionPoint point;
  23.         public PathIndexUnit customPositionType = PathIndexUnit.Distance;
  24.         public float customPosition;
  25.  
  26.         [Space]
  27.         [Header("Position")]
  28.         public Vector3 offset;
  29.        
  30.         [Space]
  31.         [Header("Rotation")]
  32.         public bool alignRotation = true;
  33.         public Vector3 addedRotation;
  34.  
  35.         private void Reset()
  36.         {
  37.             splineContainer = gameObject.GetComponentInParent<SplineContainer>();
  38.            
  39.             Apply();
  40.         }
  41.        
  42.         private void OnEnable()
  43.         {
  44.             Spline.Changed += OnSplineChanged;
  45.         }
  46.  
  47.         private void OnDisable()
  48.         {
  49.             Spline.Changed -= OnSplineChanged;
  50.         }
  51.        
  52.         private void OnSplineChanged(Spline spline, int index, SplineModification modificationType)
  53.         {
  54.             if (!splineContainer) return;
  55.  
  56.             //Spline belongs to the assigned container?
  57.             var splineIndex = Array.IndexOf(splineContainer.Splines.ToArray(), spline);
  58.             if (splineIndex < 0)
  59.                 return;
  60.  
  61.             Apply();
  62.         }
  63.  
  64.         private void OnValidate()
  65.         {
  66.             Apply();
  67.         }
  68.        
  69.         private void Apply()
  70.         {
  71.             if (!splineContainer) return;
  72.            
  73.             float t = 0f;
  74.  
  75.             switch (point)
  76.             {
  77.                 case ConnectionPoint.Start: t = 0f;
  78.                     break;                
  79.                 case ConnectionPoint.End: t = 1f;
  80.                     break;
  81.                 case ConnectionPoint.Custom: t = customPosition;
  82.                     break;
  83.             }
  84.  
  85.             if (point == ConnectionPoint.Custom && customPositionType == PathIndexUnit.Distance)
  86.             {
  87.                 t = splineContainer.Spline.ConvertIndexUnit(customPosition, PathIndexUnit.Distance, PathIndexUnit.Normalized);
  88.             }
  89.  
  90.             //Ensure a tangent can always be derived at very the start and end
  91.             t = Mathf.Clamp(t, 0.0001f, 0.9999f);
  92.  
  93.             splineContainer.Spline.Evaluate(t, out float3 splinePoint, out float3 tangent, out float3 up);
  94.  
  95.             float3 position = splinePoint;
  96.             float3 forward = math.normalize(tangent);
  97.             float3 right = -math.cross(forward, up);
  98.            
  99.             //Offset
  100.             position += right * offset.x;
  101.             position += up * offset.y;
  102.             position += forward * offset.z;
  103.            
  104.             //Position of point on spline in world-space
  105.             position = splineContainer.transform.TransformPoint(position);
  106.             this.transform.position = position;
  107.  
  108.             if (alignRotation)
  109.             {
  110.                 Quaternion rotation = Quaternion.LookRotation(forward) * Quaternion.Euler(addedRotation);
  111.                 this.transform.rotation = rotation;
  112.             }
  113.         }
  114.     }
  115. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement