methusalah / SplineMesh

A Unity plugin to create curved content in real-time with bézier curves
https://twitter.com/dumas181
MIT License
1.05k stars 104 forks source link

Modifying the position of a SplineNode only seems to change one control point #54

Closed MichaelMacha closed 2 years ago

MichaelMacha commented 2 years ago

As mentioned in my other issue report, I'm working on a game with a player running wire between devices, using SplineMesh. Right now I have it set to change its end node's Position to the transform.position of the player. This almost works, but on inspection during play, I see that only one of the control points for that final node is moving, the other is stuck in place. This causes radical curvature changes as I move the player around.

There's a very good chance that I'm missing something here, and there might be a better way to do this. Is this intentional behavior? Or is there a better way to move the control point at runtime?

MichaelMacha commented 2 years ago

It's most certainly my understanding of how nodes work... I'm now having an issue where the direction seems to consistently punch through the origin, or original location, of my player, instead of the original problem. I'll just need to humbly investigate this further before I can come up with a complete issue.

methusalah commented 2 years ago

The control points, unintuitively named "Direction" in SplineMesh, are not set in the node space but in the world space. Moving a node around won't move the associated control point and you need to move it as well.

Does it help?

MichaelMacha commented 2 years ago

I am somewhat aware of this now; it seems to have something to do with the way that the control points are getting wider as I set the node position to the relative player position, and the player walks away... however, what I'm ultimately trying to do is, consistently, set the node position to the player's position while keeping the control points at the same relative angle and scale. It's been difficult to figure out how to do.

I am using the capitalized Direction and Position, rather than direction and position, so it calls the appropriate methods; I just can't figure out how to set them properly.

On Thu, Mar 3, 2022 at 1:44 PM Benoît @.***> wrote:

The control points, unintuitively named "Direction" in SplineMesh, are not set in the node space but in the world space. Moving a node around won't move the associated control point and you need to move it as well.

Does it help?

— Reply to this email directly, view it on GitHub https://github.com/benoit-dumas/SplineMesh/issues/54#issuecomment-1058480098, or unsubscribe https://github.com/notifications/unsubscribe-auth/ABZ33Z22G3UYJO5O2TTOWBDU6EQBTANCNFSM5P3NL7NA . You are receiving this because you modified the open/close state.Message ID: @.***>

methusalah commented 2 years ago

You only have to apply the same offset to the Direction than the Position.

var playerMotion = player.position - player.previousPosition;
splineNode.Position += playerMotion;
splineNode.Direction += playerMotion;

Alternatively, you could want the direction of you wire to be always oriented to the back of your player

var curvature = Vector3.distance(player.position, nextSplineNode);
splineNode.Position = player.position;
splineNode.Direction = splineNode.Position - player.forward * curvature
// remember, the direction of the vector (Direction-Position) is where the curve is heading,
// and its magnitude represents the strength of the curvature

Alternatively, you could want the control point to be "dragged" behind the player

var curvature = Vector3.distance(player.position, nextSplineNode);
if(Vector3.distance(dragged.position, player.position) > curvature){
    dragged.position = player.position + (dragged.Position - player.position).normalized * curvature;
}
splineNode.Position = player.position;
splineNode.Direction = dragged.position;

Alternatively, you can just add the AutoSmoother component to let it decide a good Direction vector and smooth your path.

But for a dragged wire, I suppose the best result will come with a physic chain (with a simple verlet integrator for example, or Unity joints and bodies like in the rope example). Now you can create a spline out of the physic particles.

MichaelMacha commented 2 years ago

That was it. I was expecting it to be in local coordinates. Benoit Dumas, this asset is amazing and you're the best.

This does give me an idea for feature requests, though; as direction requiring global coordinates (by which I mean, needing the player's position as well as the offset) works but isn't terribly intuitive. It would be very handy to have a LocalDirection field which automates this. (I hear "direction" and I anticipate that we're looking at an absolute vector with its origin at the player's location, rather than a world coordinate.)

I'll drop it on the issues page, though.

On Fri, Mar 4, 2022 at 2:11 AM Benoît @.***> wrote:

You only have to apply the same offset to the Direction than the Position.

var playerMotion = player.position - player.previousPosition; splineNode.Position += playerMotion; splineNode.Direction += playerMotion;

Alternatively, you could want the direction of you wire to be always oriented to the back of your player

var curvature = Vector3.distance(player.position, nextSplineNode); splineNode.Position = player.position; splineNode.Direction = splineNode.Position - player.forward * curvature // remember, the direction of the vector (Direction-Position) is where the curve is heading, // and its magnitude represents the strength of the curvature

Alternatively, you could want the control point to be "dragged" behind the player

var curvature = Vector3.distance(player.position, nextSplineNode); if(Vector3.distance(dragged.position, player.position) > curvature){ dragged.position = player.position + (dragged.Position - player.position).normalized * curvature; } splineNode.Position = player.position; splineNode.Direction = dragged.position;

— Reply to this email directly, view it on GitHub https://github.com/benoit-dumas/SplineMesh/issues/54#issuecomment-1058977321, or unsubscribe https://github.com/notifications/unsubscribe-auth/ABZ33Z4NRYKOESELWWMU6PTU6HHTJANCNFSM5P3NL7NA . You are receiving this because you modified the open/close state.Message ID: @.***>

methusalah commented 2 years ago

Things would be more intuitive if at least the Direction was named differently. It is not a direction at all, as the direction is indicated by the vector Position - Direction. Also, a vector named direction is though as a normalized one, but in this case the magnitude of the vector also carry the curvature strength information. Direction is definitely a bad name.

"ControlPoint" would be better but it make immediate sense only for users that are at least a little documented about Bezier curves. "Target" may be a better choice but it is not that intuitive and fails to match the Bezier curve vocabulary. ControlPoint is probably the best option...

Also, the asset is quite old now and renaming this could cause a lot of regression on the user side.

I like the idea of having a world and local version of it.

I don't work on splineMesh anymore but if you feel like doing it, I will gladly accept a PR.

MichaelMacha commented 2 years ago

I may do that; I'm just waiting until I have a more intuitive understanding of how it works internally. The great thing about C# properties is that it's perfectly possible to have a second property which goes by a different name, but references the same internal field—like having .Feet, .Inches, and .Meters all setting and returning an internal, hidden _length field. I would suspect that this is the way to go with Direction.

Unfortunately, I still don't feel like I entirely get Direction, and what specifically it is doing. I've got all the source code to look through, though.

On Fri, Mar 4, 2022 at 9:17 AM Benoît @.***> wrote:

Things would be more intuitive if at least the Direction was named differently. It is not a direction at all, as the direction is indicated by the vector Position - Direction. Also, a vector named direction is though as a normalized one, but in this case the magnitude of the vector also carry the curvature strength information. Direction is definitely a bad name.

"ControlPoint" would be better but it make immediate sense only for users that are at least a little documented about Bezier curves. "Target" may be a better choice but it is not that intuitive and fails to match the Bezier curve vocabulary. ControlPoint is probably the best option...

Also, the asset is quite old now and renaming this could cause a lot of regression on the user side.

I like the idea of having a world and local version of it.

I don't work on splineMesh anymore but if you feel like doing it, I will gladly accept a PR.

  • Direction internally refers to ControlPoint, but is deprecated
  • ControlPoint is the new Direction
  • LocalControlPoint is a getter/setter for the internal control point relatively to the node's position.

— Reply to this email directly, view it on GitHub https://github.com/benoit-dumas/SplineMesh/issues/54#issuecomment-1059305344, or unsubscribe https://github.com/notifications/unsubscribe-auth/ABZ33Z6NM7L65PDF5IO5U2TU6IZTLANCNFSM5P3NL7NA . You are receiving this because you modified the open/close state.Message ID: @.***>