Skip to main content
Missing markup
Source Link
DMGregory
  • 136.3k
  • 22
  • 247
  • 373

If a struct type has not been given any particular value, it will usually default to a special value helpfully called default. (Though it's possible the file loading code you use does something different — you haven't shown us, so I'm assuming it's following standard C# convention).

The members of default will each hold the value corresponding to the default of their respective types: 0 for numbers, falsefalse for booleans, null for reference types, etc.

So you can check:

if (!position.Equals(default)) {/*...*/}

if (rotation != default) {/*...*/}

For a Vector3, the default value is the same as Vector3.zero, ie. (0, 0, 0), just less typing, and a bit more explicit that you're checking if it's a default value not looking for a deliberately-set value of zero.

But that highlights a bit of an issue with this code: it won't distinguish between loading an item for which no position was set, versus loading an item that was set to (0, 0, 0) deliberately.

If that distinction is important for your loading logic, then as others have suggested, you may want to change the declaration of your variable to:

[SerializeField]
Vector3? position;

This makes it a "nullable" struct — it's still a value type, but it gains an extra flag that tracks whether a value has been set.

You can check this with:

if (!position.HasValue) {/*...*/}

or, for convenience, position == null translates to this for nullable types.

Then, to access the Vector3 contents, you'd write position.Value.

You'll note that I used the .Equals() method instead of == above. That's because the equality operator for Vector3 has a built-in tolerance, so a vector very close to zero but not actually zero will return true if you compare it to a zero vector with ==. The .Equals() method only returns true for an exact match.

For quaternions, you have a somewhat easier time, in that any valid quaternion will have a non-zero value. ie. Quaternion.Dot(rotation, rotation) should be close to 1.0 — even for Quaternion.identity, which is (0, 0, 0, 1) (in x, y, z, w order).

So if you ever read an all-zero quaternion (like default), you can be sure that was not a deliberately set value, and needs to be overridden.

The difference between an all-zero quaternion and a valid one is much larger than the tolerance used in the == operator, so you don't strictly need the .Equals() method in this case.

If a struct type has not been given any particular value, it will usually default to a special value helpfully called default. (Though it's possible the file loading code you use does something different — you haven't shown us, so I'm assuming it's following standard C# convention).

The members of default will each hold the value corresponding to the default of their respective types: 0 for numbers, false for booleans, null for reference types, etc.

So you can check:

if (!position.Equals(default)) {/*...*/}

if (rotation != default) {/*...*/}

For a Vector3, the default value is the same as Vector3.zero, ie. (0, 0, 0), just less typing, and a bit more explicit that you're checking if it's a default value not looking for a deliberately-set value of zero.

But that highlights a bit of an issue with this code: it won't distinguish between loading an item for which no position was set, versus loading an item that was set to (0, 0, 0) deliberately.

If that distinction is important for your loading logic, then as others have suggested, you may want to change the declaration of your variable to:

[SerializeField]
Vector3? position;

This makes it a "nullable" struct — it's still a value type, but it gains an extra flag that tracks whether a value has been set.

You can check this with:

if (!position.HasValue) {/*...*/}

or, for convenience, position == null translates to this for nullable types.

Then, to access the Vector3 contents, you'd write position.Value.

You'll note that I used the .Equals() method instead of == above. That's because the equality operator for Vector3 has a built-in tolerance, so a vector very close to zero but not actually zero will return true if you compare it to a zero vector with ==. The .Equals() method only returns true for an exact match.

For quaternions, you have a somewhat easier time, in that any valid quaternion will have a non-zero value. ie. Quaternion.Dot(rotation, rotation) should be close to 1.0 — even for Quaternion.identity, which is (0, 0, 0, 1) (in x, y, z, w order).

So if you ever read an all-zero quaternion (like default), you can be sure that was not a deliberately set value, and needs to be overridden.

The difference between an all-zero quaternion and a valid one is much larger than the tolerance used in the == operator, so you don't strictly need the .Equals() method in this case.

If a struct type has not been given any particular value, it will usually default to a special value helpfully called default. (Though it's possible the file loading code you use does something different — you haven't shown us, so I'm assuming it's following standard C# convention).

The members of default will each hold the value corresponding to the default of their respective types: 0 for numbers, false for booleans, null for reference types, etc.

So you can check:

if (!position.Equals(default)) {/*...*/}

if (rotation != default) {/*...*/}

For a Vector3, the default value is the same as Vector3.zero, ie. (0, 0, 0), just less typing, and a bit more explicit that you're checking if it's a default value not looking for a deliberately-set value of zero.

But that highlights a bit of an issue with this code: it won't distinguish between loading an item for which no position was set, versus loading an item that was set to (0, 0, 0) deliberately.

If that distinction is important for your loading logic, then as others have suggested, you may want to change the declaration of your variable to:

[SerializeField]
Vector3? position;

This makes it a "nullable" struct — it's still a value type, but it gains an extra flag that tracks whether a value has been set.

You can check this with:

if (!position.HasValue) {/*...*/}

or, for convenience, position == null translates to this for nullable types.

Then, to access the Vector3 contents, you'd write position.Value.

You'll note that I used the .Equals() method instead of == above. That's because the equality operator for Vector3 has a built-in tolerance, so a vector very close to zero but not actually zero will return true if you compare it to a zero vector with ==. The .Equals() method only returns true for an exact match.

For quaternions, you have a somewhat easier time, in that any valid quaternion will have a non-zero value. ie. Quaternion.Dot(rotation, rotation) should be close to 1.0 — even for Quaternion.identity, which is (0, 0, 0, 1) (in x, y, z, w order).

So if you ever read an all-zero quaternion (like default), you can be sure that was not a deliberately set value, and needs to be overridden.

The difference between an all-zero quaternion and a valid one is much larger than the tolerance used in the == operator, so you don't strictly need the .Equals() method in this case.

Source Link
DMGregory
  • 136.3k
  • 22
  • 247
  • 373

If a struct type has not been given any particular value, it will usually default to a special value helpfully called default. (Though it's possible the file loading code you use does something different — you haven't shown us, so I'm assuming it's following standard C# convention).

The members of default will each hold the value corresponding to the default of their respective types: 0 for numbers, false for booleans, null for reference types, etc.

So you can check:

if (!position.Equals(default)) {/*...*/}

if (rotation != default) {/*...*/}

For a Vector3, the default value is the same as Vector3.zero, ie. (0, 0, 0), just less typing, and a bit more explicit that you're checking if it's a default value not looking for a deliberately-set value of zero.

But that highlights a bit of an issue with this code: it won't distinguish between loading an item for which no position was set, versus loading an item that was set to (0, 0, 0) deliberately.

If that distinction is important for your loading logic, then as others have suggested, you may want to change the declaration of your variable to:

[SerializeField]
Vector3? position;

This makes it a "nullable" struct — it's still a value type, but it gains an extra flag that tracks whether a value has been set.

You can check this with:

if (!position.HasValue) {/*...*/}

or, for convenience, position == null translates to this for nullable types.

Then, to access the Vector3 contents, you'd write position.Value.

You'll note that I used the .Equals() method instead of == above. That's because the equality operator for Vector3 has a built-in tolerance, so a vector very close to zero but not actually zero will return true if you compare it to a zero vector with ==. The .Equals() method only returns true for an exact match.

For quaternions, you have a somewhat easier time, in that any valid quaternion will have a non-zero value. ie. Quaternion.Dot(rotation, rotation) should be close to 1.0 — even for Quaternion.identity, which is (0, 0, 0, 1) (in x, y, z, w order).

So if you ever read an all-zero quaternion (like default), you can be sure that was not a deliberately set value, and needs to be overridden.

The difference between an all-zero quaternion and a valid one is much larger than the tolerance used in the == operator, so you don't strictly need the .Equals() method in this case.