Search Unity

Any way to set Vector3 to value of null?

Discussion in 'Scripting' started by iceshaft07, Oct 1, 2010.

  1. iceshaft07

    iceshaft07

    Joined:
    Jul 23, 2010
    Posts:
    293
    I didn't think I was going to have a problem with this since it starts off as a null value. But I'm getting an error saying I can't-- really?!
     
  2. AkilaeTribe

    AkilaeTribe

    Joined:
    Jul 4, 2010
    Posts:
    1,149
    var someVector3 : Vector3 = Vector3.zero;

    That should do it...
     
    KinderAndry and CanisMajor like this.
  3. Ntero

    Ntero

    Joined:
    Apr 29, 2010
    Posts:
    1,436
    You cannot set a value type to null (which includes data types like String, int, float, char, and also includes structs).

    You can use a Nullable Type:
    http://msdn.microsoft.com/en-us/library/1t3y8s4s(v=vs.80).aspx

    i.e. Vector3? nullableVec = null;

    But that will require casting into a normal Vector3 for use.

    Look up Value Types vs. Reference Types here:
    http://msdn.microsoft.com/en-us/library/ms173104(v=vs.80).aspx

    @AkilaeTribe
    Setting it to zero is not the same as setting it to null. As null it doesn't exist, as zero it's at a specific value.
     
    McGravity, EDartBlade and pgomes like this.
  4. AkilaeTribe

    AkilaeTribe

    Joined:
    Jul 4, 2010
    Posts:
    1,149
    *read again the first topic*

    *slaps himself*
     
  5. iceshaft07

    iceshaft07

    Joined:
    Jul 23, 2010
    Posts:
    293
    Ugh-- I hate it when languages don't support null :-(.

    At least I learned over something small; However, I still don't get why it can start off null, but you can't assign it null. That to me just seems odd.
     
  6. Ntero

    Ntero

    Joined:
    Apr 29, 2010
    Posts:
    1,436
    It does support null, with nullable types.

    The issue is memory functionality and the differences between the heap and the stack. Being able to create variables that exist on the stack and not the heap is a very good thing, however it also means you can't pass by reference, and therefore can't use null.

    It's not so much that C# doesn't support null. It's that other languages don't support creating variables on the stack.
     
    Last edited: Oct 1, 2010
  7. Eric5h5

    Eric5h5

    Volunteer Moderator Moderator

    Joined:
    Jul 19, 2006
    Posts:
    32,401
    It will never start off null; that's impossible with a struct.

    --Eric
     
  8. Ntero

    Ntero

    Joined:
    Apr 29, 2010
    Posts:
    1,436
  9. iceshaft07

    iceshaft07

    Joined:
    Jul 23, 2010
    Posts:
    293
    I'm gonna have to go back to my computer science books. From what I remember, the heap is dynamically allocated at runtime? And I think the stack was the part of the program that was loaded. Unfortunately I didn't get much experience with C++ as I wanted too, my school decided to switch to Java-- because OF COURSE that is what all the companies want now a days. Also, I found that article about the C__ Frequently Questioned Answers very interesting, even if I didn't understand every bit due to lack of C++ use.

    I should have been clearer-- I hate it when languages don't allow you the exact syntax of var = null;. I hate jumping through ropes just to do something other langauges can do in a single line (I also hate languages that don't have some built-in form of REGEX since they are so very useful).

    I'm a little bit fuzzy on my Concepts of Programming Languages, since we only studied it an never really applied it. But that's why I'm here on the forums learning it again, right (I mainly pulled out REGEXs and context sensative languages for compiler building)? Don't tell me, I htink it is better if I run into the attic and dust of that book and give a few run throughs of the chapters.

    Eric5h5-- are you sure they can't start off as null? I don't mean to question you since I have a great respect for you and your answers (as well as Dreamora), but I swear that sometimes I'll get null pointer exceptions on Vector3's I don't initialize.

    Is that some sort of variable attribute that I vaguely remember from Concepts Of Programming Languages?

    P.S. I'm using Javascript right now (not that that should matter). I have every intent on switching to C#, but the majority of my code is already written for this game and I see no point to switch yet.

    Other P.S.

    Thanks you guys for giving me such detailed answers-- I don't remember things if I don't use them.
     
  10. tomvds

    tomvds

    Joined:
    Oct 10, 2008
    Posts:
    1,028
    There is no way to ever get null into any struct type (like Vector3, Quaternion, etc.). Those exceptions you got must have come from something else.

    Anyway, on getting nullable Vector3: you can use System.Nullable<> to create a nullable Vector3:
    http://msdn.microsoft.com/en-us/library/b3h38hb0.aspx

    The declaration of the Vector3 will become a bit ugly, but it can otherwise be used as normal (while also supporting null).
     
  11. Eric5h5

    Eric5h5

    Volunteer Moderator Moderator

    Joined:
    Jul 19, 2006
    Posts:
    32,401
    Of course you can do that, but not with structs.

    Regular expressions. Note that it's not a language feature, it's a .net feature.

    Yes.

    Code (csharp):
    1. private var foo : Vector3;
    2.  
    3. function Start () {
    4.    print (foo);
    5. }
    Sorry, but no, it's just plain not possible.

    --Eric
     
  12. Ntero

    Ntero

    Joined:
    Apr 29, 2010
    Posts:
    1,436
    The Value vs. Reference types is not something that you can intrinsically know from the start, it can be a bit vague.

    I know I'm showing C# MSDN references, however they both use the same underlying compiler. So Nullable types may not function(depends if Unity added it), however the Value vs. Reference types are the same. You are pretty spot on for the Memory types, Heap is handled by the Garbage Collector, and Stack is handled based on the program order. Think stack trace for stack memory, it gets loaded and unloaded based on what part of the stack you are in.

    When an object is on the stack, it cannot be passed around, and will be destroyed upon exiting that bit of logic. This means you cannot set it to reference another variable, nor can you null it, as it will always point to the same point in memory regardless of what you do. In reference to stack memory it becomes impossible to set it to null, it's not a concept that makes sense in context to the stack.

    That doesn't mean you really need to use value types. You can create everything on the Heap, and have everything nullable. But the Heap is not as good for many things. It requires a Garbage Collector and is much slower to initialize. It is not automatically cleaned up after exitting it's scope, and must be manually checked constantly for deletion. Having every variable on the Heap is not ideal. When you have variables and data structures that are constantly created and destroyed, the stack can provide you with measurable performance gains. So C# decided to give the ability to access Stack memory directly for variables.

    I'm hoping this will help you understand the different types, and maybe even when to use which.

    I'm trying to explain that it's not so much that C# is making you jump through hoops, but rather that Java is limiting your control on memory, and reducing your ability to optimize.
    When you begin optimizing your game, especially on something like iPhone that is weak, knowing these distinctions and being able to reduce your dynamic heap allocation, and therefore your framerate-dropping Garbage Collects, can be very important.

    Note: You can use Regex in C# and Unityscript, by using the Regex .NET/mono class.
    http://msdn.microsoft.com/en-us/library/system.text.regularexpressions.regex.aspx

    You can use these in Unityscript too, you use import instead of include and should have access to the same namespaces (minus a few unimplemented features in Unityscript, like single quotes to denote a char literal).
     
  13. iceshaft07

    iceshaft07

    Joined:
    Jul 23, 2010
    Posts:
    293
    Ugh-- I wrote a relly long reply and lost all my POST input.

    I'll keep it short this time:

    Tom-- I'm going to try that :)

    Thanks for the info Eric5H5, I'm gonna try that code out (I would have done so myself, but I'm trying to finish a project right now that I hate looking at).

    Thanks for the info Ntero, I remember now (stack is stuff that gets push on from code blocks, and removed when exitted)--

    Oh, that totally helped me with heap stack; but I though that we did not have access to the heap in C# for unity / Javascript for unity?

    Actually wait a minute-- maybe I have-- that is the 'new' operator I've been seeing pop up occasionally. I haven't used it since I haven't seen any sort destructor examples, or even seen anyone deallocate something allocated by 'new'.
     
  14. Ntero

    Ntero

    Joined:
    Apr 29, 2010
    Posts:
    1,436
    New often means it goes on the heap. I say often because Vector3 overloads it's constructor to utilize the new command as a Value type, and therefore even though it uses New, it's still a Value type.

    New calls the constructor and returns an instance of that class.

    However mono (all code in Unity) has a Garbage Collector that tracks references. Every reference type in Mono keeps track of how many references it has. It knows which instances of which references are actually pointing to it's particular memory location. Once there are no more references to that object, the Garbage Collector will automatically destroy it. It handles deallocation from the heap automatically.

    Basically anything that is able to be referenced (via pointers or pass by reference) must go on the Heap and not the stack in any language, because if it was the stack, the data that reference was pointing to would be destroyed upon exiting the function, even if you try to store the reference somewhere else.
     
  15. iceshaft07

    iceshaft07

    Joined:
    Jul 23, 2010
    Posts:
    293
    So specifically, new means it can go on to the Stack or on to the Heap as far as Mono is concerned.

    Now, here is what confuses me-- in the docs, I see things like the following:

    Code (csharp):
    1.  
    2. //sorry if I didn't get the 'new' syntax 100% right
    3. var v : Vector3 = new Vector3(3,3,3);
    4.  
    Why would I want to do that instead of simply omitting the 'new' operator? Isn't that roughly the same as:

    Code (csharp):
    1.  
    2. var v : Vector3 = Vector3(3,3,3);
    3.  
    I just haven't seen what the 'new' operator buys you (since you can't manage memory yourself as far as I know with UnityScript).

    Hey, Ntero, thanks for the info you've been very helpful :).

    I'm gonna get around to testing out that code above now.
     
  16. Eric5h5

    Eric5h5

    Volunteer Moderator Moderator

    Joined:
    Jul 19, 2006
    Posts:
    32,401
    It does the same thing whether you explicitly use "new" or not.

    --Eric
     
  17. Ntero

    Ntero

    Joined:
    Apr 29, 2010
    Posts:
    1,436
    new is a special keyword for Instantiating reference types and invoking the constructor for both value and reference types.

    The two Syntax options for structs in C# are:

    var v : Vector3 = new Vector3(3,3,3);

    and

    var v : Vector3;
    v.x = 3;
    v.y = 3;
    v.z = 3;

    calling Vector3(3,3,3); without the new command will result in a compile time error(in C# at least). It's a bit of a syntax hoop to jump through, but new is required when calling Constructors in C#. I believe that Unityscript may not require that syntax, and if so there is no difference between the two calls when dealing with structs (Value types).

    However it's important to note that using new on a Reference type (class) will result in a second instance of that object. Doing new on a Value type (struct) will result in the original type being overwritten.
     
  18. iceshaft07

    iceshaft07

    Joined:
    Jul 23, 2010
    Posts:
    293
    Ok, so let me get this straight then-- Let say for instance (pardon my psuedo code, I'm not farmilar enough with C#):

    Code (csharp):
    1.  
    2. //created 1 object on the heap
    3. var class1 : MyClassA = new MyClassA();
    4.  
    5. var class2 : MyClassA = class1;
    6.  
    Is class2 a pointer to class1, or is it a copy?

    Also, how about:
    Code (csharp):
    1.  
    2. var class1 : MyClassA = new MyClassA();
    3. var class2 : MyClassA = class1;
    4.  
    5. class1 = new MyClassA();
    6.  
    Is class2 pointing to the new instance of MyClassA, or the old one (if we are talking about pointers here)?
     
  19. Chris-Sinclair

    Chris-Sinclair

    Joined:
    Jun 14, 2010
    Posts:
    1,326
    C# enforces the use of the "new" operator I believe to help eliminate the ambiguity of invoking a constructor for a type vs invoking a method available in the same scope.

    This may be a really stupid example (don't name your members/types like this!) but it illustrates why the "new" operator is used to resolve such ambiguities:
    Code (csharp):
    1. public struct Test
    2. {
    3.     public int X;
    4. }
    5.  
    6. public class SomeOtherClass
    7. {
    8.     public SomeOtherClass()
    9.     {
    10.         //if we didn't need the "new" operator, would we be
    11.         //invoking the constructor for the "Test" struct,
    12.         //or the "Test" method in SomeOtherClass?
    13.         Test t = Test();
    14.     }
    15.  
    16.         public Test Test()
    17.         {
    18.             return new Test();
    19.         }
    20. }
    EDIT: iceshaft07, if "MyClassA" is a class (which I'm guessing given its name), then in the first example, "class2" is pointing to the instance assigned to "class1". (not pointing directly to class1)

    In your second example, class 2 is pointing to the original instance, not to the newly created second instance.
     
    Last edited: Oct 4, 2010
  20. Ntero

    Ntero

    Joined:
    Apr 29, 2010
    Posts:
    1,436
    class1 and class2 are both References(read: pointers that have strict typing and the original object knows they are pointing to it) to the new MyClassA. modifying either will modify both.

    class 2 is pointing to the old instance, and class1 is pointing to the newer instance.

    if MyClassA was declared as a struct instead of a class, then in it would be direct copies and not References (fancy pointers). So each version would be pointing to it's own instance and instances could not be shared.
     
  21. Chris-Sinclair

    Chris-Sinclair

    Joined:
    Jun 14, 2010
    Posts:
    1,326
    Perhaps it should be noted given all this talk about not sharing references of structs that in C# you can use the "ref" keyword in methods to pass a struct reference in and any modifications to it reflect in the original:

    Code (csharp):
    1. int x = 10;
    2.  
    3. print(x);//outputs "10"
    4.  
    5. ModifyStruct(ref x);
    6.  
    7. print(x);//outputs "5"
    8.  
    9.  
    10.  
    11. public void ModifyStruct(ref int myIntegerReference)
    12. {
    13.     myIntegerReference = 5;
    14. }
    It's typically only used in special cases, so you don't see it too often.

    Also, it was mentioned that using nullable types will require casting to use them. The Nullable<> type actually provides properties that handle this that you should use instead of casting:
    Code (csharp):
    1. Vector3? myVector = null;
    2.  
    3. if (myVector.HasValue)
    4. {
    5.     Vector3 myNonNullVector = myVector.Value;
    6. }
     
  22. Ntero

    Ntero

    Joined:
    Apr 29, 2010
    Posts:
    1,436
    The ref keyword works, but you are still not sharing the value type.

    You can modify it within the function, but doing something like this doesn't work:

    Code (csharp):
    1.  
    2. int x = 10;
    3.  
    4. print(x);//outputs "10"
    5.  
    6. ModifyStruct(ref x);
    7.  
    8. print(x);//outputs "5"
    9.  
    10.  
    11.  
    12. public void ModifyStruct(ref int myIntegerReference)
    13. {
    14.         int newInt = myIntegerReference; //intialized by copy and not reference
    15.         newInt = 5;//this does not change the myIntegerReference variable
    16. }
    17.  
    The value type can still only be accessed by one variable. That variable is passed into the function, but at no point is it truly shared and modifiable via two different variables.

    However when passing reference types into functions it can be important to use the ref keyword if you want to share that reference to the underlying data.
     
  23. laurie

    laurie

    Joined:
    Aug 31, 2009
    Posts:
    638
    To be pedantic, there are no pointers in C#/UnityScript, only references (actually, pointers *do* exist in C#, but you wont be using them with Unity unless working with native code in a plugin). That said:

    If MyClassA is a reference type (class) then 'class1' and 'class2' are both references to the same instance of MyClassA, until the second assignment to class1. If MyClassA is a value type (struct) then class1 and class2 each hold a distinct value of type MyClassA. After the second assignment to class1, both variables hold distinct values in either case. Assigning to class1 has no effect on class2.

    To make this concrete, let's look at what happens with a Vector3 (which, as noted, is a value type):

    Code (csharp):
    1.  
    2. var v1 : Vector3 = Vector3(1,2,3);
    3. var v2 : Vector3 = v1;
    4. v1.x = 5;
    5.  
    Because Vector3 is a value type, v1 ad v2 are each assigned the value Vector3(1,2,3). They have the same value, but the value isn't shared. Therefore, after 'v1.x = 5;', v2.x is still 1. The two values are distinct. If Vector3 had been defined as a reference type (class) instead, both variables would be referencing the same instance and the change to x would be visible through both.
     
  24. iceshaft07

    iceshaft07

    Joined:
    Jul 23, 2010
    Posts:
    293
    Awesome, thanks for the info, I'll keep that in mind.

    I'll have to be very careful when reading the docs to make sure I'm looking at a class/struct before using them :).

    Offhand, do you know if there are any struct wrapper classes (a simple 'yes' they exist or 'no' they don't exist is fine) (is this on of the above MSDN docs I haven't read yet)? Similar to Java's int->Integer, float->Decimal?

    So, lets say I wanted to do something like this (yes, this is mangled between C++ and UnityScript):

    Code (csharp):
    1.  
    2. struct MyStruct
    3. {
    4.  //..things in here
    5. }
    6.  
    7. class MyStructWrapperClass
    8. {
    9.   MyStructWrapperClass (MyStruct wrapMe)
    10.   {
    11.      //..things in here
    12.   }
    13. }
    14.  
    15. void Main ()
    16. {
    17.    MyStruct ms1;
    18.    MyStruct.Init();
    19.    MyStructWrapperClass mswc1 = new MyStructWrapperClass(ms);
    20.    MyFuncThatEmulatesReferenceCopy(mswc1);
    21.    ms1.var1 = mswc1.var1;
    22.    ms1.var2 = mswc1.var2;
    23.    //etc  
    24. }
    25.  
    26. void MyFuncThatEmulatesReferenceCopy (MyStructWrapperClass inOutParam)
    27. {
    28.     //modify inOutParam, and the mswc1 also gets modified
    29. }
    30.  
    Thanks! :)
     
  25. iceshaft07

    iceshaft07

    Joined:
    Jul 23, 2010
    Posts:
    293
    Scratch the previous question-- thats called boxing :)
     
  26. iceshaft07

    iceshaft07

    Joined:
    Jul 23, 2010
    Posts:
    293
    Laurie, could you clarify me on the exact difference of a pointer and reference (I wouldn't call myself a 'baby' programmer, I just have a hard time distinguishing the difference between vocabularies and functionalities of difference languages-- for example, Java has 'methods', C++ has 'functions', and Perl has 'subroutines'-- all of which do the same thing as far as I know, and on top of that everyone calls interfaces/protocols something else as well).

    Thanks! :)
     
  27. laurie

    laurie

    Joined:
    Aug 31, 2009
    Posts:
    638
    A pointer is literally just a memory address. Change the value of the pointer, and you alter where it points rather than altering whatever it's pointing at. To get at or manipulate the value, you have to de-reference the pointer. A reference is different -- it's managed by the runtime. When you use a reference, you're implicitly using the value it's a reference to, The distinction is kinda technical, and not something you need to understand too deeply; just be aware of the terminology :)
     
  28. greysun

    greysun

    Joined:
    Feb 23, 2017
    Posts:
    9
    I know this is an ancient post but just in case someone stumbles into this c# now supports nullable types
    Vector3? myVector3 = null;
    if(myVector3.HasValue) { //do stuff}