Transform localposition is not valid

Hello, im trying this video.

Im getting error at line 28.
transform.localPosition assign attempt for ‘Square’ is not valid. Input localPosition is {1.115258, NaN, 1.000000}
This is the script

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class offset : MonoBehaviour
{
    public GameObject playerInMap;
    public RectTransform map2dEnd;
    public Transform map3dParent;
    public Transform map3dEnd;

    private Vector3 normalized, mapped;

    private void Update()
    {
        normalized = Divide(
                map3dParent.InverseTransformPoint(this.transform.position),
                map3dEnd.position - map3dParent.position
            );
        normalized.y = normalized.z;
        mapped = Multiply(normalized, map2dEnd.localPosition);
        mapped.z = 0;
        playerInMap.transform.localPosition = mapped;
    }

    private static Vector3 Divide(Vector3 a, Vector3 b)
    {
        return new Vector3(a.x / b.x, a.y / b.y, a.z / b.z);
    }

    private static Vector3 Multiply(Vector3 a, Vector3 b)
    {
        return new Vector3(a.x * b.x, a.y * b.y, a.z * b.z);
    }
}

If you get an error maybe the error message can help you?

On line 28 your are making a division and apparently you end up with NaN as a value for y.

Maybe b.y = 0 ?

What do you mean by b.y = 0? I understand that its Y = 0, but i cant find where it is. I set all my references from scene.

Im getting NaN on Z axis, when doing

Debug.Log(normalazied);

After dividing;
Yea, there for sure some problem with divide.

When diving two numbers, you have to ensure that the denominator is not zero, otherwise the result will be NaN.

So in your Divide method, if any component of b (x,y or z) is zero, then the resulting component will be NaN

I don’t really understand what you are trying to do must that is for sure a problem that you have.

Im trying to do whats in video, its for map

OK got it. Well aside the division by zero I can’t really know what is wrong with your code. It might be a setup issue in your scene. I don’t really understand your error message, it mentions a square but there is no such variable in the given script so, based on the information you provided, I can only say that the NaN value is coming from your Divide method.

The problem is that at line 23 you assign a vector that has NaN as a vector component so this won’t work for sure.

Not square, player for now, i changed it

With line 23 i get z = 0, if i comment this line i get Z NaN aswell.

I think i found the problem. the video guide is for 3d game and im in 2d game

1 Like

Obviously in 2D the above function would introduce a division by zero.
Just do

private static Vector2 Divide2D(Vector2 a, Vector2 b) {
  return new(a.x / b.x, a.y / b.y);
}

And work with 2D vectors until the very last moment to allow yourself to understand what’s going on at all times

var my2DPosition = Divide2D(whatever, divider);
myObj.transform.localPosition = toV3(my2DPosition);

private static Vector3 toV3(Vector2 v) => new(v.x, v.y, 0f);

Sadly Unity will allow implicit (basically automatic) conversion from Vector3 to Vector2 and in this process you will lose z information without any error, so be mindful of that.

I.e

Vector3 my3DVector = new(5f, 1f, 18f);
Vector2 my2DPosition = Divide2D(whatever, my3DVector);
// ^ this is an unrealistic example, but illustrates that Z is silently lost in the process

Thank you for your response!

The way I work with vector math is by implementing my own custom static library full of small snippets of reusable code. That lets you quickly formulate what you want to achieve, and still allows you to decouple or swap the original library later, if you want to make the code work standalone, or you want to bake-in some recurrent operations, or maybe you want to switch the process to SIMD operations in Unity.Mathematics and so on.

This is how I typically resolve component-wise division (again, this isn’t the most performant approach, but it is the most modular so I intentionally keep it transparent.)

public static class MyMath {
  public static Vector3 rcp(Vector3 v) => new(1f / v.x, 1f / v.y, 1f / v.z);
  public static Vector3 cmul(Vector3 a, Vector3 b) => new(a.x * b.x, a.y * b.y, a.z * b.z);
  public static Vector3 cdiv(Vector3 a, Vector3 b) => cmul(a, rcp(b));
  public static Vector2 rcp(Vector2 v) => new(1f / v.x, 1f / v.y);
  public static Vector2 cmul(Vector2 a, Vector2 b) => new(a.x * b.x, a.y * b.y);
  public static Vector2 cdiv(Vector2 a, Vector2 b) => cmul(a, rcp(b));
  ...
}

You then work with this like it’s Lego.

Also when converting I have general-purpose factory methods like so

public static Vector3 v3(Vector2 v, float z = 0f) => new(v.x, v.y, z);

Here’s another possibility because a static class also allows for extension methods

public static void setLocalPositionRotation(this Transform xf, Vector3 position, Quaternion rotation = Quaternion.identity) {
  xf.localPosition = position;
  xf.localRotation = rotation;
}

You never know when they’ll add a better, more optimized way to address this
And indeed

public static void setLocalPositionRotation(this Transform xf, Vector3 position, Quaternion rotation = Quaternion.identity)
  => xf.SetLocalPositionAndRotation(position, rotation);

Now you can compound some contextual overrides for your coding convenience in 2D

public static void setLocalPositionRotation(this Transform xf, Vector2 position, float angleInDegrees = 0f, float z = 0f) {
  var rot = angleInDegrees != 0f? rotationZ(angleInDegrees) : quat_id;
  xf.SetLocalPositionAndRotation(v3(position, z), rot);
}

public static Quaternion rotationZ(float angle) => Quaternion.AngleAxis(angle, v3_z);
public static readonly Vector3 v3_z = new(0f, 0f, 1f); // this must go to the top of the static class
public static readonly Quaternion quat_id = new(0f, 0f, 0f, 1f); // this as well

Which boils down to a very compact yet readable line in your production code

using UnityEngine;
using static MyMath; // now you can call all its functions without invoking MyMath all the time

public class MyClass {

  void Update() { // or whatever
    Vector2 my2DPosition = cdiv(vector1, vector2);
    myObj.transform.setLocalPositionRotation(my2DPosition, angleInDegrees: 45f, z: 1f);
  }

}