Search Unity

  1. Megacity Metro Demo now available. Download now.
    Dismiss Notice
  2. Unity support for visionOS is now available. Learn more in our blog post.
    Dismiss Notice

vector3 from string? (Solved)

Discussion in 'Scripting' started by darkgriffin, Apr 13, 2010.

  1. darkgriffin

    darkgriffin

    Joined:
    Nov 2, 2009
    Posts:
    113
    My solution post jump link:
    http://forum.unity3d.com/viewtopic.php?p=300180#300180

    Ok, long story short, I've got blocks in an editor with positions being saved using the command Vector3.toString().

    I can retrieve the string no problem, but then I get this in string format:

    (0.0,0.0,0.0)

    I need to get that back into a Vector3 object. Aka, an object formed by doing this:

    var newBlockVector = Vector3(x,y,z);

    The long way to do this would be to parse the string using "," as the character to parse with, calculating for the ()s placed around the number too. But that's several lines of code and three new variables to do basically the reverse of what Vector3.toString() did. :p

    I can't help but feel there must be an easier way, but I can't find one in the manual. Is there an easier way to take the result of Vector3.toString(), and plug it back into a Vector3 object?

    I basically need an "opposite" or "back conversion" for Vector3.toString(). Is there one, or do I have to stick with the long, string parsing while chopping off the ()s, way?

    Edit: Ok, my method isn't working either. I've got the string cut down to three variables, but they are still string type so Unity won't accept them as valid values in the Vector3(x,y,z) constructor. How do I convert a string to a value I can plug into Vector3(x,y,z) constructor? (I know these will always be numbers as returned by Vector3.toString, so the user won't be able to put funky things like "bob" into the formula.)
     
  2. Quietus2

    Quietus2

    Joined:
    Mar 28, 2008
    Posts:
    2,058
    Write a function to do it. That's the function of a function!

    It's not that many lines of code as you seem to think either. Trim the first and last chars, use split to break it up with the comma delimiter then throw them into float.Parse.

    Use those 3 values and return a vector3. Win!
     
  3. darkgriffin

    darkgriffin

    Joined:
    Nov 2, 2009
    Posts:
    113
    Ok, I've got it boiled down to this:

    Code (csharp):
    1. function getBlockVector3(blockDataString : String) {
    2.     //gets and returns the vector3 from a blockDataString
    3.     var returnstring : String;
    4.     var startChar = 0;
    5.     var endChar = blockDataString.IndexOf(blockStringParseChar);
    6.    
    7.     returnstring = blockDataString.Substring(startChar, endChar);
    8.    
    9.     startChar = 1;
    10.     endChar = returnstring.IndexOf(",");
    11.     lastEnd = endChar;
    12.     returnx = System.Convert.ToDecimal(returnstring.Substring(startChar,endChar-1));
    13.    
    14.     startChar = lastEnd+1;
    15.     endChar = returnstring.IndexOf(",", lastEnd);
    16.     lastEnd = endChar;
    17.     returny = System.Convert.ToDecimal(returnstring.Substring(startChar,endChar));
    18.    
    19.     startChar = lastEnd+1;
    20.     endChar = returnstring.IndexOf(",", lastEnd);
    21.     lastEnd = endChar;
    22.     returnz = System.Convert.ToDecimal(returnstring.Substring(startChar,endChar));
    23.    
    24.     print(returnx + "  " + returny + "  " + returnz);
    25.        
    26.     returnVector3 = Vector3(returnx,returny,returnz);
    27.    
    28.     return returnVector3;
    29. }
    I'm sure there is probably some easier/more sane way, but it works. Since I'm new to parsing stuff using .net, I don't know how I'd write a function to do the actual parsing over the string returned from Vector3.toString(). :oops: I'm sure there's a better way, cause this looks like a lot of code for something so simple.

    I guess for starters, I could make a function that does this part:

    Code (csharp):
    1.     startChar = 1;
    2.     endChar = returnstring.IndexOf(",");
    3.     lastEnd = endChar;
    4.     returnx = System.Convert.ToDecimal(returnstring.Substring(startChar,endChar-1));
    5.    
    6.     startChar = lastEnd+1;
    7.     endChar = returnstring.IndexOf(",", lastEnd);
    8.     lastEnd = endChar;
    9.     returny = System.Convert.ToDecimal(returnstring.Substring(startChar,endChar));
    10.    
    11.     startChar = lastEnd+1;
    12.     endChar = returnstring.IndexOf(",", lastEnd);
    13.     lastEnd = endChar;
    14.     returnz = System.Convert.ToDecimal(returnstring.Substring(startChar,endChar));
    I guess I'll try that next, and see how it goes from there. Like I said, I'm totally new to using .net to parse stuff, and parsing stuff in general, so it's really difficult for me to get my head around how to grab what I need off the strings. But I'm learning and getting there. :D
     
  4. darkgriffin

    darkgriffin

    Joined:
    Nov 2, 2009
    Posts:
    113
    Ok, here's the function I wrote. It's in no way optimized, in fact, I'm a total newbie at this so it's probably really really bad as far as code vs work done with it. But I figured I'd share it anyway.

    Feel free to improve on it as you see fit, and do share any improvements or better methods you have to parse the outcome of a vector3.toString(). I'm sure others would appreciate not having to write this from scratch:

    Code (csharp):
    1. //Vector3fromString
    2. //A useful function to convert back from a given Vector3.toString() output.  Passes back a Unity Vector3 object.
    3. function Vector3FromString(Vector3string) {
    4.     //get first number (x)
    5.     startChar = 1;
    6.     endChar = Vector3string.IndexOf(",");
    7.     lastEnd = endChar;
    8.     returnx = System.Convert.ToDecimal(Vector3string.Substring(startChar,endChar-1));
    9.     //get second number (y)
    10.     startChar = lastEnd+1;
    11.     endChar = Vector3string.IndexOf(",", lastEnd);
    12.     lastEnd = endChar;
    13.     returny = System.Convert.ToDecimal(Vector3string.Substring(startChar,endChar));
    14.     //get third number (z)
    15.     startChar = lastEnd+1;
    16.     endChar = Vector3string.IndexOf(",", lastEnd);
    17.     lastEnd = endChar;
    18.     returnz = System.Convert.ToDecimal(Vector3string.Substring(startChar,endChar));
    19.     //build a new vector3 object using the values we've parsed
    20.     returnvector3 = Vector3(returnx,returny,returnz);
    21.     //pass back a vector3 type
    22.     return returnvector3;
    23. }
    To use this function, just use the following:

    Code (csharp):
    1. var NewVector3 = Vector3FromString(Vector3string);
    In this example, NewVector3 will be a Vector3 type, pointing to the location that Vector3string points to.

    It goes without saying you need to pass it a string exactly like what the output of Vector3.toString() is. It's got no error checking whatsoever, so Unity will throw a fit if you pass it anything else. An example of what Vector3string is expected to look like:

    Code (csharp):
    1. (0.0, 0.0, 0.0)
    Onward and upward then! Next up, a bunch of backend stuff for the editor's data formats so I can use all this new code for something besides a print statement. :D
     
  5. Quietus2

    Quietus2

    Joined:
    Mar 28, 2008
    Posts:
    2,058
    Yeah that is a bit much.

    1 - Use Midstring to get rid of the parenthesis.
    2 - Use String.split to parse the delimited values into an array.

    Two commands and done, then you're ready to return the values from parse.float as a vector3.
     
  6. darkgriffin

    darkgriffin

    Joined:
    Nov 2, 2009
    Posts:
    113
    Hmm, I can't find a Midstring command in the .net documentation. :oops: Searching the documentation results in only three hits, and none of them are very helpful to me. I don't think the string class in .net has a Midstring function. :?

    String.split works, but then I don't know what you're talking about with the whole parse.float thing. It's probably something really simple, but I'm not getting it.

    I'll poke some more I guess, but without documentation on what to pass string.Midstring(), I have no idea what I am doing anymore. Unity is tossing unhelpful "command not a subset of whatever" type errors at me, so I'm evedently doing it wrong.

    I'm also having a second problem. My names of prefabs(it's stored as a string in the level array) are being cut to 15 characters. I'm using the following to get the string:

    Code (csharp):
    1.  
    2. function getBlockPrefabName(blockDataString) {
    3.     //gets and returns the PrefabName from a blockDataString
    4.     var returnstring : String;
    5.     var startChar = blockDataString.IndexOf(blockStringParseChar) + 1;
    6.     var endChar = blockDataString.IndexOf(blockStringParseChar, startChar-1);
    7.     //  NOT WORKING, RETURN IS CUT OFF DOWN TO 15 CHARS!    returnstring = blockDataString.Substring(startChar,endChar);
    8.    
    9.     return returnstring;
    10. }
    But my block entry of this string:

    Code (csharp):
    1. "city1x1floor prefab"
    Is returning this in the console when parsed with the above:

    Code (csharp):
    1. city1x1floor pr
    As you can see, it's being cut down somewhere between retreval and being printed by the print statement. I have no idea why. :oops:

    Obveously, this won't work right if the game tries to spawn a "city1x1floor pr" from the game library, so I need to find out two things:

    -Why is Unity cutting it down to 15 characters when the original string, and what I've asked for, is much longer?

    -How can I fix this and force it to use as many characters are needed? (My prefabs may end up with lots of long names as we develop the game further, and the format is supposed to be name based, as I want to keep it simple and not mess with a constantly changing id table of blocks.)

    EDIT: Ignore the second problem, I'm apparently more of an idiot then I thought I was. The second value to pass into Substring() is LENGTH, not the character to stop at. Which explains why, with data that started 15 characters into the text, I kept getting back 15 characters. Sometimes, I feel silly. :oops: :D
     
  7. Quietus2

    Quietus2

    Joined:
    Mar 28, 2008
    Posts:
    2,058
    I believe in the .net string class it's simply called Mid, as opposed to MidString or Mid$. Yep, here it is.

    http://msdn.microsoft.com/en-us/library/wffts6k3(VS.85).aspx

    You can use parse to convert a string to a float value.

    http://msdn.microsoft.com/en-us/library/fd84bdyt(VS.100).aspx
     
  8. darkgriffin

    darkgriffin

    Joined:
    Nov 2, 2009
    Posts:
    113
    Why does this throw a Missing Method Exception if the string object has the Mid function?

    Code (csharp):
    1. Vector3string.Mid(Vector3string,1,lengCut);
    The other new code I wrote up before that works fine:

    Code (csharp):
    1. lengCut = Vector3string.Length - 1;
    Which returns 14, the length of Vector3string minus 1(so I can cut off the last ")" character).

    But I can't get Mid working or recognized at all. What am I doing wrong? :?
     
  9. Quietus2

    Quietus2

    Joined:
    Mar 28, 2008
    Posts:
    2,058
    That's awfully strange. I appears .net has it but mono does not. I also noticed the mono string class documentation is pretty poor. Full of "to be filled in later."

    Code (csharp):
    1.  Vector3string  = Vector3string.Substring(Vector3string,1, Vector3string.length - 2);
    That should work. Mid does essentially the same thing as substring, but indexes from 1 where substr indexes from 0.
     
  10. darkgriffin

    darkgriffin

    Joined:
    Nov 2, 2009
    Posts:
    113
    Thanks, that works.

    Unfortunetly, the documentations, as you said, are pretty useless. Because of this, I can't figure out how to use ToArray() to create the array parsing with ",". Which leaves me back at the old, long method of getting the data.

    I really could use a documentation that actually has javascript examples for use in Unity. It's very confusing trying to convert the C++ examples into the Unity Javascript language, especally for new coders like me. :(

    For now, despite the terribleness of my first solution, it's the only one I've managed to actually make work without running into commands I have no idea how to type. I know there has to be a better way to do this, but I need to just take what works and move on for now.

    Thanks for all your help!
     
  11. Quietus2

    Quietus2

    Joined:
    Mar 28, 2008
    Posts:
    2,058
    Here you go. I had 3 minutes while I was eating lunch. Give it a string and it will return your vector3. No for loops, counters or any such stuff.

    Code (csharp):
    1.  
    2. function parseVector3(sourceString : String) {
    3.  
    4.       var outString : String;
    5.       var outVector3 : Vector3;
    6.       var splitString = new Array();
    7.  
    8.    // Trim extranious parenthesis
    9.    
    10.    outString = sourceString.Substring(1, sourceString.length - 2);
    11.  
    12.    // Split delimted values into an array
    13.    
    14.    splitString = outString.Split("," [0]);
    15.    
    16.    // Build new Vector3 from array elements
    17.    
    18.    outVector3.x = parseFloat(splitString[0]);
    19.    outVector3.y = parseFloat(splitString[1]);
    20.    outVector3.z = parseFloat(splitString[2]);
    21.    
    22. return outVector3;
    23.  
    24. }
    25.  
    Yeah some things are painful. You can generally get a jist of how things are supposed to work from a combination of web javascript examples and the .net documentation.

    But as you've seen that doesn't always works. It sometimes takes a search of the forums for other people who have used the method/class and experimentation.

    I'm not sure if it's really up to unity to document Javascript and C# though. The user community has some nice writeups on the idiosyncrasies that you will find on the Unity wiki.
     
    tokar_dev likes this.
  12. darkgriffin

    darkgriffin

    Joined:
    Nov 2, 2009
    Posts:
    113
    It worked! Yay!

    Now that I see it in action, I think I understand how to use string.Split().

    I also didn't know there was a parseFloat(). I've actually had a question about that, why can't we just dump the resulting array of splitString into the Vector3 object? Then I realized that the Vector3 object is storing the numbers in it's .x, .y, and .z properties. So we still need to split the data into the three variables, because otherwise we're tossing a plain Array into a more complicated object, and Unity throws a fit.

    Thanks so much for all your time, teaching, and patience. I've learned a lot from this little activity. :)
     
  13. ravinder

    ravinder

    Joined:
    Aug 25, 2010
    Posts:
    150
    Thanks for the code. It worked.
     
  14. Remix000

    Remix000

    Joined:
    Jul 11, 2012
    Posts:
    3
    A pretty compact C# version of a string to Vector3 parsing function:

    Code (csharp):
    1.  
    2. public Vector3 getVector3(string rString){
    3.     string[] temp = rString.Substring(1,rString.Length-2).Split(',');
    4.     float x = float.Parse(temp[0]);
    5.     float y = float.Parse(temp[1]);
    6.     float z = float.Parse(temp[2]);
    7.     Vector3 rValue = new Vector3(x,y,z);
    8.     return rValue;
    9. }
    10.  
     
    seansteezy and nxrighthere like this.
  15. ravinder

    ravinder

    Joined:
    Aug 25, 2010
    Posts:
    150
    yes it's better one, I had used a similar approach posted by Remix000. Infact it's the simplest and easiest one
     
  16. HenningKO

    HenningKO

    Joined:
    Dec 17, 2015
    Posts:
    1
    Even compact-er:

    Code (CSharp):
    1. public Vector3 stringToVec(string s) {
    2.     string[] temp = s.Substring (1, s.Length-2).Split (',');
    3.     return new Vector3 (float.Parse(temp[0]), float.Parse(temp[1]), float.Parse(temp[2]));
    4. }
    thanks for the tips, Quietus.
     
    borjamtez likes this.
  17. mistergreen2016

    mistergreen2016

    Joined:
    Dec 4, 2016
    Posts:
    226
    This might be old but if you serialize the vectors to JSON for instance, it is broken up in the the component x,y,z for you, so you don't need to parse or even convert to string.
     
    amazingjaba likes this.