0
\$\begingroup\$

I run into the problem with moving object regarding to its rotation. The thing is that I'm changing object position by assigning new transform.localPosition value. In specific cases I want to modify assigned value by slightly changing z axis (height) of the object.

I tried to do it with use of transform.up. I expected move along local z axis (like in Unity scene preview), but it doesn't work as expected.

transform.Translate(Vector3.up, Space.Self) works exactly as I want, but as I said I want to combine it with transform.localPosition i already use. How should I modify passed Vector3 so it works correctly?


The class below is used to simulate move of an object around sphere. For example plane flying around Earth. I adjust plane rotation so it's chassis is facing Earth. Object is moving on the Earth surface though. I want to move it slightly up so it flies. That's why I want to move it along local z axis as it is distance from the core of the Earth.

Full class snippet (I'm using LeanTouch package)

public Transform lookAtTarget;
RaycastHit hit;
RaycastHit lastHit;

public float rotationSmoothTime = 0.3F;
public float moveSmoothTime = 0.3F;
private Vector3 rotationVelocity = Vector3.zero;
private Vector3 moveVelocity = Vector3.zero;
private Vector3 lastNewRightDir;

protected virtual void Awake ()
{
    Use.UpdateRequiredSelectable (gameObject);
    lastNewRightDir = transform.right;
}

void Update ()
{
    var fingers = Use.GetFingers ();
    if (fingers.Count < 1)
    {
        Move (lastFingerScreenPosition, Vector2.zero);
        return;
    }
    LeanFinger finger = fingers[0];
    Move (finger.ScreenPosition, finger.ScreenDelta);
    lastFingerScreenPosition = finger.ScreenPosition;
}

public void Move (Vector2 fingerScreenPosition, Vector2 scaledDelta)
{
    var ray = Camera.main.ScreenPointToRay (fingerScreenPosition);
    LayerMask mask = LayerMask.GetMask ("Interactable");

    bool newHit = Physics.Raycast (ray, out hit, float.PositiveInfinity, mask);

    Vector3 rightDir = transform.right;
    Vector3 newRightDir = lastNewRightDir;

    Vector3 targetPosition = lastHit.point;

    if (newHit)
    {
        targetPosition = hit.point;
        lastHit = hit;
    }
    else if (lastHit.distance == 0)
    {
        return;
    }

    Vector3 forwardDir = (targetPosition - lookAtTarget.position).normalized;

    if (targetPosition != transform.position && scaledDelta != Vector2.zero)
    {
        newRightDir = (targetPosition - transform.position).normalized;
        lastNewRightDir = newRightDir;
    }

    rightDir = Vector3.SmoothDamp (rightDir, newRightDir, ref rotationVelocity, rotationSmoothTime);
    Vector3 upwardDir = Vector3.Cross (forwardDir, rightDir);
    transform.rotation = Quaternion.LookRotation (forwardDir, upwardDir);


    transform.localPosition = Vector3.SmoothDamp (transform.localPosition, targetPosition, ref moveVelocity, moveSmoothTime);
}}

Before transform.localPosition = Vector3.SmoothDamp (transform.localPosition, targetPosition, ref moveVelocity, moveSmoothTime); the targetPosition value should be adjusted so object moves 1 unit alongside local z axis.

\$\endgroup\$
4
  • \$\begingroup\$ @Zibelas I'm setting it this way. The targetPosition variable is based on raycast hit. transform.localPosition = Vector3.SmoothDamp (transform.localPosition, targetPosition, ref moveVelocity, moveSmoothTime); The thing is that y axis is height of the object. During move object should be lets say 1 unit above ground. So i want to add this value to targetPosition. Vector3.up won't work correctly as I want to apply this 1 unit based on transform rotation, not global rotation. I though transform.up would work this way, but clearly I'm wrong. \$\endgroup\$
    – Ardoos
    Commented Oct 28, 2020 at 11:35
  • \$\begingroup\$ @Zibelas I updated my question with class snippet. I hope it helps with understanding my issue. \$\endgroup\$
    – Ardoos
    Commented Oct 28, 2020 at 11:57
  • \$\begingroup\$ why are you using transform.rotation and not transform.localRotation? \$\endgroup\$
    – Zibelas
    Commented Oct 28, 2020 at 12:18
  • \$\begingroup\$ To be honest I didn't think setting height would be such a problem and it was easier for me to calculate it that way. I don't think it's a problem though. Plane is rotated correctly and setting it using transform.localRotation would give the same result. \$\endgroup\$
    – Ardoos
    Commented Oct 28, 2020 at 13:23

1 Answer 1

2
\$\begingroup\$

transform.up is a vector in world space, but transform.localPosition moves an object in its parent's space. If the parent (or grandparent, etc) is rotated, then these two spaces can differ.

To get the object's up vector relative to its parent coordinate system, just multiply:

Vector3 localUpInParentSpace = transform.localRotation * Vector3.up;

Then you can add it to your localPosition:

upwardShift = 1.0f; // Substitute whatever distance you want to move here.
Vector3 shiftedLocalPosition = transform.localPosition + localUpInParentSpace * upwardShift;

This moves along the object's local y+ axis. If you want to move along the object's local z+ axis, use Vector3.forward instead of Vector3.up.

\$\endgroup\$
1
  • \$\begingroup\$ Thanks, that is exactly what I was trying to do! \$\endgroup\$
    – Ardoos
    Commented Oct 29, 2020 at 8:08

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .