Added NavMesh link support.

This commit is contained in:
Alexander Filippov 2024-03-26 01:56:15 +01:00
parent ac200e9085
commit 6b0748c755
3 changed files with 101 additions and 87 deletions

View File

@ -6,6 +6,9 @@ using System.IO;
using System.Text;
using Unity.Mathematics;
using System.Collections.Generic;
using System.Linq;
using Unity.AI.Navigation;
using UnityEngine.AI;
namespace FrameJosh.SplineImporter
{
@ -22,91 +25,97 @@ namespace FrameJosh.SplineImporter
if (GUILayout.Button("Import Spline"))
{
SplineImporter splineImporter = target as SplineImporter;
var splineImporter = (SplineImporter)target;
splineImporter.name = splineImporter.splineData.name;
SplineData splineData = JsonUtility.FromJson<SplineData>(splineImporter.splineData.text);
SplineContainer splineContainer = splineImporter.GetComponent<SplineContainer>();
foreach (UnityEngine.Splines.Spline thisSpline in splineContainer.Splines)
splineContainer.RemoveSpline(thisSpline);
foreach (SplineData.Spline thisDataSpline in splineData.splines)
var splineData = JsonUtility.FromJson<SplineData>(splineImporter.splineData.text);
var splineContainer = splineImporter.GetComponent<SplineContainer>();
foreach (var thisSpline in splineContainer.Splines) splineContainer.RemoveSpline(thisSpline);
#if COM_UNITY_AI_NAVIGATION
Undo.IncrementCurrentGroup();
var children = (from Transform child in splineImporter.transform select child.gameObject).ToList();
children.ForEach(Undo.DestroyObjectImmediate);
#endif
foreach (var thisDataSpline in splineData.splines)
{
UnityEngine.Splines.Spline thisSpline = splineContainer.AddSpline();
var thisSpline = splineContainer.AddSpline();
thisSpline.Closed = thisDataSpline.closed;
foreach (ControlPoint thisControlPoint in thisDataSpline.controlPoints)
foreach (var thisControlPoint in thisDataSpline.controlPoints)
{
Vector3 position = PositionToVector(thisControlPoint.position);
var position = thisControlPoint.position;
var handleL = thisControlPoint.handleL;
var handleR = thisControlPoint.handleR;
var rotation = Quaternion.LookRotation((float3)handleR - position, Vector3.up) *
Quaternion.AngleAxis(-thisControlPoint.tilt, Vector3.forward);
Vector3 handleL = PositionToVector(thisControlPoint.handleL);
float3x3 rotationMatrix = new(rotation);
Vector3 handleR = PositionToVector(thisControlPoint.handleR);
Quaternion rotation = Quaternion.LookRotation(handleR - position, Vector3.up) * Quaternion.AngleAxis(-thisControlPoint.tilt, Vector3.forward);
float3x3 rotationMatrix = new float3x3(rotation);
thisSpline.Add(new()
{
Position = position * splineImporter.scale,
Rotation = rotation,
TangentIn = ((Vector3)math.mul(handleL - position, rotationMatrix)) * splineImporter.scale,
TangentOut = ((Vector3)math.mul(handleR - position, rotationMatrix)) * splineImporter.scale
},
TangentMode.Broken);
thisSpline.Add(new BezierKnot
{
Position = position * splineImporter.scale,
Rotation = rotation,
TangentIn = math.mul((float3)handleL - position, rotationMatrix) * splineImporter.scale,
TangentOut = math.mul((float3)handleR - position, rotationMatrix) * splineImporter.scale
},
TangentMode.Broken);
}
#if COM_UNITY_AI_NAVIGATION
if (thisDataSpline.closed) continue;
var go = new GameObject
{
transform =
{
parent = splineImporter.transform
}
};
var link = go.AddComponent<NavMeshLink>();
var startPoint = thisDataSpline.controlPoints[0].position * splineImporter.scale;
if (NavMesh.SamplePosition(startPoint, out var startHit, 2f, NavMesh.AllAreas))
startPoint = startHit.position;
var endPoint = thisDataSpline.controlPoints[^1].position * splineImporter.scale;
if (NavMesh.SamplePosition(endPoint, out var endHit, 2f, NavMesh.AllAreas))
endPoint = endHit.position;
link.startPoint = startPoint;
link.endPoint = endPoint;
Undo.RegisterCreatedObjectUndo(go, $"Create link from {startPoint} to {endPoint}");
#endif
}
}
if (GUILayout.Button("Export Spline"))
{
SplineImporter splineImporter = target as SplineImporter;
var splineImporter = (SplineImporter)target;
if (!splineImporter.splineData)
{
string path = "Assets" + EditorUtility.SaveFilePanel("Save .JSON", "", "New Spline.json", "json").Substring(Application.dataPath.Length);
var path = "Assets" +
EditorUtility.SaveFilePanel("Save .JSON", "", "New Spline.json", "json")[
Application.dataPath.Length..];
if (path.Length > 0)
{
File.WriteAllBytes(path, Encoding.ASCII.GetBytes(""));
AssetDatabase.Refresh();
TextAsset textAsset = AssetDatabase.LoadAssetAtPath(path, typeof(TextAsset)) as TextAsset;
var textAsset = AssetDatabase.LoadAssetAtPath(path, typeof(TextAsset)) as TextAsset;
splineImporter.splineData = textAsset;
}
else return;
}
SplineContainer splineContainer = splineImporter.GetComponent<SplineContainer>();
SplineData splineData = new();
splineData.splines = new SplineData.Spline[splineContainer.Splines.Count];
List<SplineData.Spline> dataSplines = new();
foreach (UnityEngine.Splines.Spline thisSpline in splineContainer.Splines)
var splineContainer = splineImporter.GetComponent<SplineContainer>();
SplineData splineData = new()
{
splines = new Spline[splineContainer.Splines.Count]
};
List<Spline> dataSplines = new();
foreach (var thisSpline in splineContainer.Splines)
{
List<ControlPoint> controlPoints = new();
foreach (BezierKnot thisBezierKnot in thisSpline.Knots)
foreach (var thisBezierKnot in thisSpline.Knots)
{
Position position = VectorToPosition(thisBezierKnot.Position);
float3x3 rotationMatrix = new float3x3(Quaternion.Inverse(thisBezierKnot.Rotation));
Position handleL = VectorToPosition(math.mul(thisBezierKnot.TangentIn, rotationMatrix) + thisBezierKnot.Position);
Position handleR = VectorToPosition(math.mul(thisBezierKnot.TangentOut, rotationMatrix) + thisBezierKnot.Position);
controlPoints.Add(new()
Position position = thisBezierKnot.Position;
float3x3 rotationMatrix = new(Quaternion.Inverse(thisBezierKnot.Rotation));
Position handleL = math.mul(thisBezierKnot.TangentIn, rotationMatrix) + thisBezierKnot.Position;
Position handleR = math.mul(thisBezierKnot.TangentOut, rotationMatrix) +
thisBezierKnot.Position;
controlPoints.Add(new ControlPoint
{
position = position,
handleL = handleL,
@ -114,7 +123,7 @@ namespace FrameJosh.SplineImporter
});
}
dataSplines.Add(new()
dataSplines.Add(new Spline
{
controlPoints = controlPoints.ToArray(),
closed = thisSpline.Closed
@ -123,12 +132,14 @@ namespace FrameJosh.SplineImporter
splineData.splines = dataSplines.ToArray();
File.WriteAllText(AssetDatabase.GetAssetPath(splineImporter.splineData), JsonUtility.ToJson(splineData, true));
File.WriteAllText(AssetDatabase.GetAssetPath(splineImporter.splineData),
JsonUtility.ToJson(splineData, true));
AssetDatabase.Refresh();
}
}
}
[RequireComponent(typeof(SplineContainer))]
#endif
public class SplineImporter : MonoBehaviour
@ -136,22 +147,7 @@ namespace FrameJosh.SplineImporter
#if UNITY_EDITOR
public TextAsset splineData;
public float3 scale = new (1f, 1f, 1f);
public static Vector3 PositionToVector(Position position)
{
return new(position.x, position.z, position.y);
}
public static Position VectorToPosition(Vector3 vector)
{
return new()
{
x = vector.x,
y = vector.z,
z = vector.y
};
}
public float3 scale = new(1f, 1f, 1f);
#endif
}
#if UNITY_EDITOR
@ -162,21 +158,31 @@ namespace FrameJosh.SplineImporter
public struct Position
{
public float x;
public float y;
public float z;
public static implicit operator Position(float3 vector)
{
return new Position
{
x = vector.x,
y = vector.z,
z = vector.y
};
}
public static implicit operator float3(Position vector)
{
return new float3(vector.x, vector.z, vector.y);
}
}
[Serializable]
public struct ControlPoint
{
public Position position;
public Position handleL;
public Position handleR;
public float tilt;
}
@ -188,7 +194,7 @@ namespace FrameJosh.SplineImporter
public bool closed;
}
public Spline[] splines = new Spline[0];
public Spline[] splines = Array.Empty<Spline>();
}
#endif
}

View File

@ -3,7 +3,8 @@
"rootNamespace": "",
"references": [
"Unity.Splines",
"Unity.Mathematics"
"Unity.Mathematics",
"Unity.AI.Navigation"
],
"includePlatforms": [],
"excludePlatforms": [],
@ -12,6 +13,12 @@
"precompiledReferences": [],
"autoReferenced": true,
"defineConstraints": [],
"versionDefines": [],
"versionDefines": [
{
"name": "com.unity.ai.navigation",
"expression": "",
"define": "COM_UNITY_AI_NAVIGATION"
}
],
"noEngineReferences": false
}

View File

@ -1,13 +1,14 @@
{
"name": "ru.shazbot.spline-importer",
"version": "2.0.2",
"version": "3.0.0",
"displayName": "Spline Importer",
"description": "Import and export splines between Blender and Unity.",
"unity": "2021.3",
"dependencies": {
"com.unity.modules.jsonserialize": "1.0.0",
"com.unity.mathematics": "1.2.6",
"com.unity.splines": "2.5.1"
},
},
"author": {
"name": "Alexander Filippov",
"email": "alexander@shazbot.ru",