Address LinearVelocity, AlignOrientation, and LineForce pain points

As a Roblox developer, it is currently too hard to switch to the new constraints for a variety of common use cases.

If Roblox is able to address this issue, it would improve my development experience because it would allow for migration away from legacy BodyMovers.

I have taken the time to attempt to convert all of the legacy bodymovers in a game that heavily utilizes them to the new constraints, however I found multiple pretty major problems that prevent the new constraints from fitting a lot of common usecases in our game. This is not an exhaustive list of problems and it’s rather small, I know that there are likely more problems.

Detailed problems with some use cases

  • LinearVelocity applies its force at the attachment point.
    • Unlike a BodyVelocity (or BodyThrust), this means that the assembly cannot rotate, as this would require the linear velocity’s attachment point to be accelerated away from its target.
    • At first you might think that it would be sufficient to change the RelativeTo mode to Attachment0 if the attachment is part of the assembly, however this doesn’t result in a change in behaviour, and this changing behaviour would be undesirable for many use cases.
    • In conclusion, LinearVelocity is currently not capable of replacing BodyVelocity if the goal is simply to accelerate a craft, which may rotate and have forces applied that cause the craft to rotate.
  • AlignOrientation has no valid configuration that can reproduce the effect of having PerAxis force limits.
    • You may think that it would be viable to use the perpendicular align, however this creates two points of stability as opposed to one and is a massive hassle to use.
    • A common use case is disallowing rotational forces from being applied on only the X or Z axis (to keep the top of an assembly facing upwards), but allowing the AlignOrientation to rotate an object on the Y axis.
    • This would actually be a significant improvement over BodyGyro if it had a PerAxis mode, because this would allow assigning angular force limits relative to the assembly.

Motivations in our game (our use actual cases in practice)

  • BodyGyro is used within a vehicle’s seat, to let players rotate the vehicle. Our game previously offered some different modes of control, except for one of them, which allowed the craft to rotate freely on the Y axis (preferably this would actually be its own Y axis but this is not something BodyGyros can do).
  • BodyVelocity is used within a variety of thruster objects which players can build with. They each have different pros and cons. Problematically, LinearVelocity makes vehicles extremely difficult to rotate, because the full force of the velocity must be overcome by other constraints like AlignOrientation.
  • BodyGyro is used to let some

Key takeaways, some solutions to these problems, and some further improvements to constraints relevant to the above use cases

  • AlignOrientation definitely needs PerAxis force limits, it currently can’t reproduce the behaviour of BodyGyro without it.
  • LinearVelocity needs to have the option to be able to counteract any of its own forces that would fight torques in the assembly.
    • The desired behaviour is that this makes the LinearVelocity’s forces ‘in the frame of reference of’ the assembly. From the assembly’s perspective, it is never rotating.
    • A property reminiscent of this idea called ReactionTorqueEnabled exists in AlignOrientation and might be a suitable name (it would need to default to enabled to avoid breakage).
  • The above option should absolutely be available for VectorForce as well, because currently (and this is the case for BodyForce too so this is not a parity issue) if a craft tries to rotate it will actively be fought by the force the VectorForce applies which is often not desirable behaviour.
  • Speed limits for VectorForce would also create a better behaviour for use cases that LinearVelocity would be used for, and that BodyVelocity was already often used for despite having some undesirable characteristics (notably deceleration).
    • This would likely want to come in both Magnitue and PerAxis flavors.
    • Sometimes you want something to be accelerated up to a certain speed, but you do not want it to be decelerated.
    • This would allow for multiple forms of propulsion on one assembly. For example, one that accelerates extremely quickly to reach a moderate speed (e.g. 200 sps), and another with a lower acceleration but higher (or even unlimited) max speed.
    • This would result in far more intuitive ‘thrusters’ and would be an objective improvement over BodyVelocity, LinearVelocity, BodyForce, etc for this use case.
4 Likes

Thanks for the feedback!

LinearVelocity applies its force at the attachment point

Forces generate torque when applied in a position other than the center of mass. You can address this via:
LinearVelocity.Attachment0.WorldPosition = Attachment.Parent.AssemblyCenterOfMass
VectorForce has a ApplyAtCenterOfMass toggle which creates the same effect.

A common use case is disallowing rotational forces from being applied on only the X or Z axis (to keep the top of an assembly facing upwards), but allowing the AlignOrientation to rotate an object on the Y axis.

Use an AlignOrientation with PrimaryAxisParallel mode, to lock the X and Z axis, leaving Y free. Then, use a second AlignOrientation or other constraint to drive rotation on the Y axis. Different torque magnitudes can be used in each.


These are approaches you can use today to achieve these results. Your other feedback regarding hassle of use and complexity is totally valid. We want to continue to improve tooling such that achieving these use cases gets down to be less effort than the BodyMovers - I can acknowledge we aren’t there yet.

For the speed limits idea, I agree it would be useful to have an object like this. Could this could be achieved with LinearVelocity and a script that toggles between speed targets and force magnitudes?

3 Likes

As a developer who’s tried their best to switch over systems from the old BodyMovers to constraints, I would like to point out – a big focus for the API design should be accessibility & ease of use. I remember having had to create five different constraints, and then one-to-two attachments for every single one of these constraints.

It is an incredibly large hassle and ask to make of developers, especially those who are used to the comfort of BodyMovers – which are easy to setup, debug, and get working. I don’t need to setup attachments and parent them into Terrain so that I can properly move an object to a destination in the way I want it; I can just create an object, set its constraints and target, parent and then destroy it all within ten lines of code. Creating such temporary forces with constraints however, becomes exhausting quickly – especially given how I need to properly destroy the attachments for every single constraint associated with it also.

3 Likes

Not to mention attachments are awful to work with in the datamodel! Seriously, why are only BasePart parents allowed?

Setting up constraints would become 10x easier if we could just parent attachments elsewhere, and potentially even switch over to a no-attachment-use-basepart-center mode.

3 Likes

We’ve made a lot of improvements here that I don’t think the whole community has been made fully aware of. For example, the need for having second attachments on Terrain should be no more. All mover constraints provide a single attachment mode. And remember, you can also connect multiple constraints to the same attachment.

Very temporary forces can use the impulse API, otherwise I often find it simpler to build complex things at edit time, and clone them with code and toggle Enabled properties. Parenting and unparenting is a less performant pattern.

1 Like

Thanks for providing these solutions, I think they’ll be helpful for anyone that comes across this later. I did think of a potential issue with the proposed AlignOrientation solution but I haven’t tried the solution yet so I’m not sure if this is the behaviour in practice.

Setting the attachment to the center of mass did resolve the other issue I was having really nicely, and while it took me some thought to understand exactly why it makes sense in hindsight, it’s just not immediately obvious if you’re not really thinking about the way the physics works out. It would be pretty intuitive (and just good QoL for people trying to migrate away from BodyMovers) as a property of some kind.


I believe that maybe PrimaryAxisParallel will also create two stable states (one with the PrimaryAxis aiming up, one with the PrimaryAxis aiming down). If this does end up being the case (which would technically make this not parallel which is why I’m thinking that it probably does behave in the way I was imagining) then as an alternative PrimaryAxisLookAt would certainly do what I want, albeit I’d have to update & compute a target position on heartbeat, which, isn’t super convenient but would definitely solve my problem and also isn’t really that hard.

Something like a PrimaryAxisLookAlong AlignType could be a great in-engine solution I think, and it would be consistent considering the existence of CFrame.lookAt and CFrame.lookAlong. In OneAttachment mode this could be relative to the world, and in TwoAttachment mode it could be in the relative space of Attachment1 (e.g. 0, 0, -1 would be the look vector of Attachment1, basically equivalent to AllAxes mode but the assembly could spin freely around the look direction)

Both could also do with the ability to set an optional up vector via SecondaryAxis for full parity, albeit how to make this optional isn’t immediately clear to me. I figured maybe setting SecondaryAxis to 0,0,0 to disable it but this isn’t nicely backwards compatible and would require SecondaryAxis being able to be 0,0,0 in that circumstance which is potentially a bit weird.

2 Likes