Search Unity

  1. Welcome to the Unity Forums! Please take the time to read our Code of Conduct to familiarize yourself with the forum rules and how to post constructively.
  2. Dismiss Notice

Question Transform.TransformPoint(offset) in combination with Rigidbody.MovePosition behaves weirdly

Discussion in 'Scripting' started by TheMatrixAgent22, Aug 14, 2023.

  1. TheMatrixAgent22

    TheMatrixAgent22

    Joined:
    Jul 9, 2017
    Posts:
    41
    Hello!
    I'm trying to move a rigidbody using this. I want to set its position in local space, and this is what I came up with in a few seconds, thinking it would work without issues:
    rb.MovePosition(targetTransform.TransformPoint(positionInLocalSpace));

    I've also tried this with
    rb.position = ...

    If I set (0,0,0) for
    positionInLocalSpace
    , the rigidbody stands still. Though if I change it to (1,0,0) for example, I get the object moving like something along the lines of:
    (14, 15, -20)
    (43, 35, -60)
    (89, 58, -75)
    etc.

    Transform.TransformVector
    and
    Transform.TransformDirection
    always returns
    (0,0,0) + positionInLocalSpace
    in world space... which makes sense, since it's not supposed to be used like this.
    Do you guys know what I'm doing wrong here?
    Thanks a lot in advance,
    Alvin

    P.S.:
    Debug.Log(targetTransform.TransformPoint(positionInLocalSpace))
    returns exactly what is expected, but the rigidbody doesn't move in the correct direciton.
     
    Last edited: Aug 14, 2023
  2. Bunny83

    Bunny83

    Joined:
    Oct 18, 2010
    Posts:
    3,495
    It's not clear what targetTransform is. Is it the transform of the rigidbody itself? If that's the case your reference would move when you move the object. So yes, the local position stays the same but of course the world space position would not. So it's a bit difficult to actually disect your issue here without knowing what targetTransform is and how it relates to your "rb".

    You do understand the concept of local space, right? If you consider yourself as an object and you use a local position like (0,0,1), that position would be 1m in front of you. So no matter where you are or in which direction you're facing, the position is always 1m right in front of you. When you move yourself to that position, of course the worldspace position of your local position would change since the reference changed.
     
  3. TheMatrixAgent22

    TheMatrixAgent22

    Joined:
    Jul 9, 2017
    Posts:
    41
    Thanks a lot for your reply! targetTransform is the transform with the rigidbody. What I'm trying to do, is simply set the localPosition of the targetTransform using rb.MovePosition. rb.MovePosition moves the gameObject to that position in world space, and I need to set it using local space. The problem is, this doesn't happen... the object (with the rigidbody) moves in a seemingly-random direction constantly, and doesn't stop until I set
    positionInLocalSpace
    to (0,0,0).
    To put it simply, my goal is to use Rigidbody.MovePosition with local space, instead of world space.
     
  4. Bunny83

    Bunny83

    Joined:
    Oct 18, 2010
    Posts:
    3,495
    Well, in that case my assumption was correct and everything works as expected. What exactly did you expect? You probably execute that code every frame, right?

    If your object is located at (10,24,5) and is not rotated at all, the local position (1,2,-5) projected into worldspace would be (11,26,0) since the local space position is relative to your object. So when you move your object to that new position the now projected local space position of (1,2,-5) would be (12,28,-5) since you moved your object. If you just want to move the object to a relative position you would need to do that ONCE. Because once you moved to that new position, the relative position of your desired worldspace target position is now (0,0,0) since it is 0m away from your current position. So when you keep that local position offset, you're going to add it to your position every frame.
     
  5. TheMatrixAgent22

    TheMatrixAgent22

    Joined:
    Jul 9, 2017
    Posts:
    41
    AHHH OK!!! Your explenation makes a lot of sense, I get it! My problem is that the object is constantly affected by force. I want the object to simply move back to positionInLocalSpace. How can I do that if I can't put it in FixedUpdate?
     
  6. Bunny83

    Bunny83

    Joined:
    Oct 18, 2010
    Posts:
    3,495
    But this simply doesn't make sense. At one instance in time you may stand outside on the street and you see a light post about 10m in front of you. So the location of that light post is +10m in your local space. However when you start walking towards that light post it's no longer 10m away since you get closer. So it may only be 9m now in your local space. So you can not fix a local position when you change your reference. You may calculate the worldspace position of your desired target position based on your initial local position, but then keep the worldspace position as a target to move towards.

    Note that "MovePosition" would move your object instantly to that target position, not gradually. So where does your local position actually came from? Why is it a local position in the first place if your goal is to reach a certain world space point (like that light post in my example)?
     
  7. TheMatrixAgent22

    TheMatrixAgent22

    Joined:
    Jul 9, 2017
    Posts:
    41
    I see... then what SHOULD work, is taking the local 0,0,0 and translating it in world space. That would mean the target would simply move towards the position of its parent. Shouldn't this code
    rb.MovePosition(target.TransformPoint(Vector3.zero))
    do exactly that? If this would work, I could just do
    target.TransformPoint(Vector3.zero) + offset
    .

    P.S.: Thanks a lot for your patience!
     
  8. spiney199

    spiney199

    Joined:
    Feb 11, 2021
    Posts:
    5,769
    Why not just use it's word position + an offset? You're just adding unnecessary steps. You know the position of your target, so just use it's world position.
     
    Bunny83 likes this.
  9. Bunny83

    Bunny83

    Joined:
    Oct 18, 2010
    Posts:
    3,495
    This:
    Code (CSharp):
    1. target.TransformPoint(Vector3.zero)
    is literally the same as
    Code (CSharp):
    1. target.position
    So moving an object to it's own current position of course does nothing. I'm still confused. Do you understand what a relative / local position is? It's relative to it's space. When the reference of that space changes, the absolute position of a fix relative position will also change.

    You said
    Moving back to a certain local position doesn't make much sense since as you moved, the actual position would have changed.

    You still haven't told us what this is all about. Where does this local position come from and why is it a local position and not a worldspace position? Maybe you're using the wrong "local space"? Every object has it's own local space.
     
  10. TheMatrixAgent22

    TheMatrixAgent22

    Joined:
    Jul 9, 2017
    Posts:
    41
    Maybe you're right and I'm doing lots of unneccessary steps. Basically what I'm working on is an IK system for the arms. Since I don't want the arms to clip into walls, I added colliders to the 'target' of the IK and a rigidbody. I want the arms to be pushed back if they push against the wall, but then (and this is the part I'm struggling with), I want to move the arms back to their position. The positionInLocalSpace is exactly that position. Since the coordinates in world space would be constantly changing based on the player's position, I want to set the local position (since the 'target' moves with the player). I also can't simply use transform.localPosition, since that would once again 'bypass' physics.
    Is there a better way to do it than idea I thought of?
     
  11. TheMatrixAgent22

    TheMatrixAgent22

    Joined:
    Jul 9, 2017
    Posts:
    41
    Code (CSharp):
    1. Transform parentTransform = target.parent;
    2. Matrix4x4 parentMatrix = parentTransform != null ? parentTransform.localToWorldMatrix : Matrix4x4.identity;
    3. Vector3 worldPosition = parentMatrix.MultiplyPoint3x4(localPositionOffset);
    This code seems to do it. I had to take a whole different approach to this.
    worldPosition
    is the position you can use with rb.MovePosition of course.