# Altering a single axis of a Vector3 in local space?

Hi everyone. =)

I have a script in which I need to make a new Vector3 variable based on one I already have, but to the left a little.
This script runs on an object which can be facing different directions, so if I just adjust the x value directly, like I have here(apologies for the less than clear variable names):

var leftTopEndLeft            = leftInnerEndTop;
leftTopEndLeft.x          = leftTopEndLeft.x - 0.5;

This adjusts the x axis in world space, not local space.
I’ve had a look at transform.InverseTransformDirection and transform.InverseTransformPoint and I assume I need to use one of these in some way, but I can’t quite wrap my head around how to implement it in this situation.

I’d be very grateful for any help and advice. Thanks for taking a look. =)

This [C# code] should work for offsetting from the local orientation of the object by 5 along the negative x-axis of the GameObject.

Vector3 newPosition = transform.localToWorldMatrix * (new Vector3(-5, 0, 0));

Basically, you’re taking the local coordinate relative to the transform’s coordinate system and converting it to what it would be in world space after its Parent(s) transformations and the local Scale, Rotation then Translation operations of the Transform are performed.

You can use this script to visually see how it works with something like Gizmos

using UnityEngine;
using System.Collections;

[ExecuteInEditMode]
public class ___TestScript304 : MonoBehaviour
{
public Vector3 leftInnerEndTop = new Vector3(-2, 5f, 0);
public Vector3 leftTopEndLeft;
public float size = 0.25f;

void OnDrawGizmos()
{
// Change the Gizmos matrix to be that of the transform's localToWorldMatrix conversion
Gizmos.matrix = transform.localToWorldMatrix;

// Because the matrix is set to the transform's localToWorldMatrix conversion, coordinates relative to the object's local axis' can be used

// Draw leftInnerEndTop
Gizmos.color = Color.white;
Gizmos.DrawWireSphere(leftInnerEndTop, size);

// Draw leftTopEndLeft
Gizmos.color = Color.cyan;
Gizmos.DrawWireSphere(leftTopEndLeft, size);

// Draw a line that represents the positive local x-axis direction
Gizmos.color = Color.red;
Gizmos.DrawLine(Vector3.zero, new Vector3(1f, 0, 0));

// Draw a line that represents the positive local y-axis direction
Gizmos.color = Color.green;
Gizmos.DrawLine(Vector3.zero, new Vector3(0, 1f, 0));

// Draw a line that represents the positive local z-axis direction
Gizmos.color = Color.blue;
Gizmos.DrawLine(Vector3.zero, new Vector3(0, 0, 1f));
}

// Use this for initialization
void Start()
{

}

// Update is called once per frame
void Update()
{
leftTopEndLeft = new Vector3(leftInnerEndTop.x - 0.5f, leftInnerEndTop.y, leftInnerEndTop.z);
}
}

Edit: Changed the Gizmos example to include your variables, though I have no idea exactly what the value of leftInnerEndTop is.

I’ve been a bit wary of touching any matrix related stuff due to inexperience, so I wouldn’t have thought to try using that.
I comprehend your explanation of how it works to some degree, but I’ll have to work on understanding it better. It always bothers me to use code when I don’t know how it does what it does. =P
I initially tried this:

var leftOuterStartTop        = leftInnerStartTop;
leftOuterStartTop        = transform.localToWorldMatrix * (new Vector3(-0.5,0,0));

Which, as one imagines, led to the point being offset by 0.5 at world center, rather than the position I wanted. I almost posted here seeking further clarification before realizing I could just do this:

var leftOuterStartTop        = leftInnerStartTop + (transform.localToWorldMatrix * (new Vector3(-0.5,0,0)));

It seems to work so far, but as I said, I’m somewhat inexperienced with this. Does it seem about right?

I don’t know how leftInnerStartTop is being assigned so its difficult for me to judge how you should or shouldn’t assign it.

I’m assuming you want to do something like this.

var leftOuterStartTop = (transform.localToWorldMatrix * (new Vector3(-0.5f,0,0) + leftInnerStartTop));

What this is currently being used for is to create meshes that bridge two objects. I have a set of empty gameObjects that are used to represent where the initial verts should be, then adjust values in the script based around this.
leftInnerStartTop was just the position of one of the empty objects I mentioned before.
I needed to adjust the local x value to build the walls on the left and right, so for the wall on the left I would need to get the local x value minus 0.5, and the reverse for the wall on the right.

Currently the code I posted does the job without issue. Is the snippet you posted more efficient or less error prone? Or just a cleaner way of writing it?

Thank you very much for your help and patience so far. =)

Oh okay, then leftInnerStartTop is a world position, so your code is indeed correct.

I was under the assumption that leftInnerStartTop was a local coordinate. You can ignore my last post [before this one] in this case.

Ah, I see. I’ll keep your last post in mind for when I do need to use a local coordinate.
Thank you very much for your time, you’ve been a great help. =)

There’s a trick with 2D vectors on rotating them exactly 90 degrees. You merely swap X and Y and then negate the Y. Negating both X and Y of the original will reverse the direction of the vector 180 degrees. So, you can combine that if the 90 degree rotation is in the wrong direction.

3D is more complicated. There really isn’t any such thing as 3D rotation; all rotations are 2D rotations performed in 3D. In other words, X, Y, and Z have to be rotated independently. You can use quaternions, but quaternions are 4D complex (imaginary) numbers. So that’s not in 3D; you’re introducing a 4th dimension to make the rotation happen.

Anyway, in 3D, “left” is not so easily defined. Obviously, you mean 90 degrees to port or 90 degrees of yaw in the local space.

What you’re doing looks right. Basically, you have to determine what left is by rotating 90 degrees to port. Whatever direction that points, that’s “left”. That’s a 90 degree local yaw. The local to world matrix seems to be doing that for you. Or at least its providing a matrix that will rotate anything from world space into local space. So when applied to you left pointing vector in world space it rotates it into local space and now it points left locally. By adding it to the original vector you should get a new vector with the position -0.5 units left of the head of the original vector. To go from the original vectors tail (at the origin) you shouldn’t have to add it back to the original vector.

I hope to produce a YouTube video on matrices before the end of this year (in the next month).

1 Like