- Home /
Rigidbody constraints in local space?
The position and rotation constraints you can set for rigidbodies are in world space. Is there a way to constrain a rigidbody's position and rotation in local space? I couldn't find an answer with Google, just a lot of other people asking the same question.
Answer by OhNoDinos · Feb 16, 2014 at 12:42 AM
I realize this question is old, but I recently solved this problem myself, if any other people come stumbling across this thread.
Khada's response is correct, but in order to actually achieve this, you can use the following code (C#).
Vector3 localVelocity = transform.InverseTransformDirection(rigidbody.velocity);
localVelocity.x = 0;
localVelocity.z = 0;
rigidbody.velocity = transform.TransformDirection(localVelocity);
This translates the rigidbody's velocity into local space, constrains the values you need, then translates it back. This particular code constrains x and z movement in local space.
Thank you OhNoDinos, I was looking for this also. Do you know if its also possible to do the same with rigidbody.position?, so The rigidbody stays at the same height, Regards.
Great job!! I was struggling with this, and it worked for me just fine! :)
Hello, I wonder if this works if the rigidbody is pushed by a kinematic rigidbody.
Basically, I want to make a button, and there is a kinematic rigidbody collider attached to the player's hand. The button has a rigidbody and a spring joint.
If I freeze the rigidbody constraints, the button won't be pushed by the hand along any of the global axes I froze. However, if I don't tick the rigidbody constraints but only use your code or use other kinematic rigidbody colliders on the button's sides to prevent it from moving to unwanted positions, the body will just keep jittering. And if I push it over the colliders that blocks the button, the button will just remain on the other side of the collider.
Answer by jeyb · Jul 19, 2016 at 08:04 PM
Just in case anyone comes across this old question, in Unity 5 rigidbody constraints are applied in local space: https://docs.unity3d.com/ScriptReference/Rigidbody-constraints.html
Although the docs say this, I think it's a mistake because they still lock in world for me on 5.5...
it's written that: position constraints are applied in World space, and rotation constraints are applied in Local space.
Wrong. "Freeze Position" property still works in world space not local space.
Answer by Khada · Feb 22, 2013 at 06:48 PM
In short, no. Rigid bodies don't do calculations in local space and in general an object with a rigid body shouldn't be the child of another object.
What you can do is constrain the axes that you want to behave differently and code the behavior yourself.
Answer by kamran-bigdely · Jul 13, 2017 at 10:49 PM
I noticed that setting local position to zero was effective to constrain a rigidbody's position along specific axis :
public class FreezeLocalAxes : MonoBehaviour {
private Rigidbody _rigidbody;
private float _localX = 0;
private float _localY = 0;
private float _localZ = 0;
public bool _freezeAlongX = false;
public bool _freezeAlongY = false;
public bool _freezeAlongZ = false;
// Use this for initialization
void Start () {
_rigidbody = gameObject.GetComponent<Rigidbody>();
}
void Update () {
_localX = transform.localPosition.x;
_localY = transform.localPosition.y;
_localZ = transform.localPosition.z;
if (_freezeAlongX) _localX = 0;
if (_freezeAlongY) _localY = 0;
if (_freezeAlongZ) _localZ = 0;
gameObject.transform.localPosition = new Vector3(_localX, _localY, _localZ);
}
}
If you want to freeze the rotation along a specific axis, just mark them in Rigidbody component because they are already in local coordinates (in contrast with 'freeze position' which is in world coordinate system).
Answer by swalex · Mar 06, 2016 at 01:55 PM
You can attach following behaviour script to your rigidbody game object to keep it always at a plane or beam cutting / pointing at a target transform:
using System;
using UnityEngine;
[RequireComponent( typeof( Rigidbody ) )]
public class CameraRail : MonoBehaviour
{
[Flags]
public enum LockFlags
{
None,
Horizontal,
Vertical,
Both
}
[Range( 0, 25 )]
public float Force = 1;
public LockFlags Lock = LockFlags.Both;
public Transform Target;
private Rigidbody _rigidbody;
private Transform _transform;
public void Awake()
{
_rigidbody = GetComponent<Rigidbody>();
_transform = GetComponent<Transform>();
}
public void Update()
{
if ( Lock == LockFlags.None || Force <= 0 ) return;
bool lockX = ( Lock & LockFlags.Horizontal ) == LockFlags.Horizontal;
bool lockY = ( Lock & LockFlags.Vertical ) == LockFlags.Vertical;
Vector3 velocity = _transform.InverseTransformDirection( _rigidbody.velocity );
if ( lockX ) velocity.x = 0;
if ( lockY ) velocity.y = 0;
_rigidbody.velocity = _transform.TransformDirection( velocity );
Vector3 distance = Target.position - _transform.position;
Vector3 idealPosition = Target.position - _transform.forward * distance.magnitude;
Vector3 correction = idealPosition - _transform.position;
correction = _transform.InverseTransformDirection( correction );
if ( !lockX ) correction.x = 0;
if ( !lockY ) correction.y = 0;
correction.z = 0;
correction = _transform.TransformDirection( correction );
_rigidbody.velocity += correction * Force;
}
}
Your answer
Follow this Question
Related Questions
Rotate and transform in local space 2 Answers
Objects not always Spawning At Correct Location 2 Answers
how to ignore transform.position.y 3 Answers
Prefab Character position/rotation resets 0 Answers
Objects Instantiating at wrong position 3 Answers