Wayback Machinekoobas.hobune.stream
May JUN Jul
Previous capture 13 Next capture
2021 2022 2023
1 capture
13 Jun 22 - 13 Jun 22
sparklines
Close Help
  • Products
  • Solutions
  • Made with Unity
  • Learning
  • Support & Services
  • Community
  • Asset Store
  • Get Unity

UNITY ACCOUNT

You need a Unity Account to shop in the Online and Asset Stores, participate in the Unity Community and manage your license portfolio. Login Create account
  • Blog
  • Forums
  • Answers
  • Evangelists
  • User Groups
  • Beta Program
  • Advisory Panel

Navigation

  • Home
  • Products
  • Solutions
  • Made with Unity
  • Learning
  • Support & Services
  • Community
    • Blog
    • Forums
    • Answers
    • Evangelists
    • User Groups
    • Beta Program
    • Advisory Panel

Unity account

You need a Unity Account to shop in the Online and Asset Stores, participate in the Unity Community and manage your license portfolio. Login Create account

Language

  • Chinese
  • Spanish
  • Japanese
  • Korean
  • Portuguese
  • Ask a question
  • Spaces
    • Default
    • Help Room
    • META
    • Moderators
    • Topics
    • Questions
    • Users
    • Badges
  • Home /
avatar image
2
Question by chanfort · Nov 16, 2014 at 05:44 PM · inputstring

Recovering function from input string

I am looking for a way how to allow user to input function and get it's value at certain points. Lets say I have:

 public string independentArgument = "x";
 public string myFunction = "x*x";
 
 public float x = 3.1f;
 public float y;
 
 void Start(){
     y = GetValue( independentArgument, myFunction, x );
     print(y);
 }
 
 float GetValue(string s1, string s2, float f1){
     float f2;
     
         ???
 
     return f2
 }

The question here is how to "search" myFunction string to build up expression for y calculation?

Comment
Add comment
10 |3000 characters needed characters left characters exceeded
▼
  • Viewable by all users
  • Viewable by moderators
  • Viewable by moderators and the original poster
  • Advanced visibility
Viewable by all users

2 Replies

· Add your reply
  • Sort: 
avatar image
2
Best Answer

Answer by Bunny83 · Nov 19, 2014 at 04:52 PM

I've written a very simple expression parser some time ago. I just posted it on the wiki (ExpressionParser). It also allows you to specify custom functions. It works entirely on double values. It supports most functions from the System.Math class.

Simple example of how to add a custom method:

 var parser = new ExpressionParser();
 // add fibonacci function. Takes zero based index
 parser.AddFunc("fib", (p) =>{
     double V1 = 1;
     double V2 = 0;
     int count = (int)p.FirstOrDefault();
     for(int i = 0; i < count; i++)
     {
         double V = V1 + V2;
         V2 = V1;
         V1 = V;
     }
     return V1;
 });

 var f = parser.EvaluateExpression("fib(x)").ToDelegate("x");
 for (int i = 0; i < 20; i++ )
     Debug.Log("("+i+")" + f(i));

edit
Since i haven't tested the parser in Unity it had some errors due to .NET / Mono incompatibilities. I've fixed those (small) errors and created an example:

ExpressionParserTest(requires webplayer)

I've added links to the parser and the script for this demo below the webplayer. The scene just contains a camera with the ExpressionParserTest.cs attached.

Some notes on the demo:

  • all unknown parameters are simply fed with the same "x"-value

  • the x value goes from -100 to +100 with a step size of 0.1 So it calculates 2000 values each time it's drawn.

  • The time "constant" is simple Unity's Time.time.

  • I've added a "repeat" and "pingpong" function which works the same as Unity's

  • The visible screen area goes from -100 to 100 in x and -50 to 50 in y

Comment
Add comment · Show 7 · Share
10 |3000 characters needed characters left characters exceeded
▼
  • Viewable by all users
  • Viewable by moderators
  • Viewable by moderators and the original poster
  • Advanced visibility
Viewable by all users
avatar image chanfort · Nov 21, 2014 at 11:18 PM 0
Share

When I save the class from wiki to ExpressionParser.cs file I getting two errors appearing:

 Assets/scripts/ExpressionParser.cs(73,34): error CS1502: The best overloaded method match for `string.Join(string, string[])' has some invalid arguments

and the second one:

 Assets/scripts/ExpressionParser.cs(73,34): error CS1503: Argument `#2' cannot convert `System.Collections.Generic.IEnumerable<string>' expression to type `string[]'

Any idea how to fix them?

avatar image Bunny83 · Nov 21, 2014 at 11:26 PM 0
Share

Yes, sure... It looks like $$anonymous$$ono doesn't have the string.Join overload that takes an IEnumerable... I'll add a .ToArray ^^

I've written and tested the class in Visual Studio. Since it just uses standard classes i would have expected it to work out of the box...

What do you mean by "add the whole function together"? I don't get that...

edit
@chanfort:
Ok, i've replaced everything that caused problems (was more than i expected...)

avatar image Bunny83 · Nov 22, 2014 at 01:22 AM 0
Share

@chanfort: Just in case you haven't seen the edit, I've added an example ;)

avatar image chanfort · Nov 22, 2014 at 02:13 AM 0
Share

Wonderfull, it works like a charm now!

Oh, forget about previous comment - I was just thinking that it was like a method, but it's a set of classes.

By the way, you can also try to build a simple usage "helper" class, which would take just strings as input, uses all namespaces, etc inside it and returns to end user double or float :)

But in general it's very great job, as it calculates all these $$anonymous$$athf functions and allows users to enter their equations

We can finally close this question.

avatar image Bunny83 · Nov 22, 2014 at 03:16 AM 0
Share

@chanfort: Hmm, i'm not sure what kind of helper you have in $$anonymous$$d. When you have created a parser object for parameter less expressions you can use

 double val = parser.Evaluate("5+3^4-5/7");

When you have parameters you either have to create a delegate or use the expression that is returned by EvaluateExpression:

 ExpressionDelegate func = parser.EvaluateExpression("x^3 - 3*x^2").ToDelegate("x");
 double val = func(45);

$$anonymous$$eep in $$anonymous$$d that you can derive a custom parser from ExpressionParser and add more custom methods / "constants":

 public class $$anonymous$$yParser : ExpressionParser
 {
     public $$anonymous$$yParser()
     {
         AddConst("time",()=>Time.time);
     }
 }
 
 var parser = new $$anonymous$$yParser();
 double time2 = parser.Evaluate("time * 2");

Any other "usage helpers" depends on the usage you need. For example if you want to be able to pass a variable amount of parameters and values, the values also need to be passed as string as you can only have 1 params array. Example:

 public static float Eval(string aExpression, params string[] aParams)
 {
     if (aParams.Length %2 != 0)
         return 0; // wrong parameter count
     var exp = Expression.Parse(aExpression);
     for(int i = 0; i < aParams.Length; i+=2)
     {
         exp.Parameters[aParams[i]].Value = double.Parse(aParams[i+1]);
     }
     return (float)exp.Value;
 }

This could be used like that:

 float v = Eval("sqrt(x^2+y^2)","x","5","y","6");

So the method takes pairs of a parameter name and the parameter value as string. However i don't see a good usage for this. If you pass wrong things to the parameter names / values you most likely will get an exception of some sort.

Show more comments
avatar image
2

Answer by AlwaysSunny · Nov 16, 2014 at 03:10 PM

If I understand what you're saying, it's a pretty complex topic. (Parsing) First you decide upon the rules by which the user can enter their string o' commands, operators, variables, then code a solution which analyzes a string, breaking those components into individual commands, operators, and variables to create a sensible operation. Research parsing, string analysis, and regular expressions. Probably'll need to use hashtables also for passing around your freshly parsed elements.

Comment
Add comment · Show 4 · Share
10 |3000 characters needed characters left characters exceeded
▼
  • Viewable by all users
  • Viewable by moderators
  • Viewable by moderators and the original poster
  • Advanced visibility
Viewable by all users
avatar image Scribe · Nov 16, 2014 at 06:42 PM 0
Share

If you are willing to use unityscript as opposed to C# then you can use the built in eval command:

 var x : float;
 var f : String = "x*x";
 
 function Update () {
     if(Input.Get$$anonymous$$eyDown($$anonymous$$eyCode.Q)){
         Debug.Log(eval(f));
     }
 }
avatar image chanfort · Nov 16, 2014 at 11:40 PM 0
Share

I found quite nice way in this question: http://answers.unity3d.com/questions/34349/how-to-evaluate-a-mathematical-expression-in-unity.html where I replace x with numbers:

     public static double Evaluate(string independentArgument, string expression, string argumentValue)
      {
          var doc = new System.Xml.XPath.XPathDocument(new System.IO.StringReader("<r/>"));
          var nav = doc.CreateNavigator();
          var newString = expression;
          newString = (new System.Text.RegularExpressions.Regex(@"([\+\-\*])")).Replace(newString, " ${1} ");
          newString = newString.Replace("/", " div ").Replace("%", " mod ").Replace(independentArgument, argumentValue);
          return (double)nav.Evaluate("number(" + newString + ")");
      }

It works quite well, but I can't access more complicated functions, like Abs(), Pow() or Exp()

Can anyone recognise if it is calculated through X$$anonymous$$L language or something else?

avatar image chanfort · Nov 19, 2014 at 12:55 PM 0
Share

It seems to work quite well with simple algebra but there is still one big question outstanding: how to use more complicated functions. This involves:

  1. Is it accessing through X$$anonymous$$L language and calculating in C# ? If so, maybe it is not very difficult to use C# functions?

  2. If it's not possible, maybe more complex functions can be approximated with simple ones, i.e. using Taylor expansion, etc.

These are open questions, which should be good to cover to close this thread.

avatar image Bunny83 · Nov 19, 2014 at 05:11 PM 0
Share

@chanfort: The XPath classes provides a framework to query an X$$anonymous$$L document with XPath. XPath is not part of X$$anonymous$$L itself. However as far as i know all those classes are bundled in the System.Xml assembly which is quite large (since it contains a lot classes) and will significantly increase your code-base size. Unless you use the X$$anonymous$$L classes anyways or you don't care about the size you can use the expression parser that's part of the XPath framework.

It is possible to add custom methods to the XPath parser, though it's quite complicated. XPath is ment to be used to process X$$anonymous$$L documents.

Your answer

Hint: You can notify a user about this post by typing @username

Up to 2 attachments (including images) can be used with a maximum of 524.3 kB each and 1.0 MB total.

Follow this Question

Answers Answers and Comments

3 People are following this question.

avatar image avatar image avatar image

Related Questions

Gui list and color 0 Answers

Input keycode string not working 2 Answers

Help In Making a SphereCast for 3D Tire! Working RayCast Script included! 0 Answers

Using Input.GetJoystickNames 1 Answer

Word or string position under mouse position 1 Answer


Enterprise
Social Q&A

Social
Subscribe on YouTube social-youtube Follow on LinkedIn social-linkedin Follow on Twitter social-twitter Follow on Facebook social-facebook Follow on Instagram social-instagram

Footer

  • Purchase
    • Products
    • Subscription
    • Asset Store
    • Unity Gear
    • Resellers
  • Education
    • Students
    • Educators
    • Certification
    • Learn
    • Center of Excellence
  • Download
    • Unity
    • Beta Program
  • Unity Labs
    • Labs
    • Publications
  • Resources
    • Learn platform
    • Community
    • Documentation
    • Unity QA
    • FAQ
    • Services Status
    • Connect
  • About Unity
    • About Us
    • Blog
    • Events
    • Careers
    • Contact
    • Press
    • Partners
    • Affiliates
    • Security
Copyright © 2020 Unity Technologies
  • Legal
  • Privacy Policy
  • Cookies
  • Do Not Sell My Personal Information
  • Cookies Settings
"Unity", Unity logos, and other Unity trademarks are trademarks or registered trademarks of Unity Technologies or its affiliates in the U.S. and elsewhere (more info here). Other names or brands are trademarks of their respective owners.
  • Anonymous
  • Sign in
  • Create
  • Ask a question
  • Spaces
  • Default
  • Help Room
  • META
  • Moderators
  • Explore
  • Topics
  • Questions
  • Users
  • Badges