<?xml version="1.0" encoding="UTF-8" standalone="yes"?><oembed><version><![CDATA[1.0]]></version><provider_name><![CDATA[Ondrej Paska Blog]]></provider_name><provider_url><![CDATA[https://fishtrone.wordpress.com]]></provider_url><author_name><![CDATA[Ondrej Paska]]></author_name><author_url><![CDATA[https://fishtrone.wordpress.com/author/randalfien/]]></author_url><title><![CDATA[Connecting Unity Editor to Google&nbsp;Sheets]]></title><type><![CDATA[link]]></type><html><![CDATA[<p>If you worked in Unity for a while, you&#8217;ve probably seen some plugins, like the I2 Localization, that can connect and sync with Google Sheets. It seemed like magic to me, so I decided to take a look at how it&#8217;s done and it turns out to be super simple.</p>
<p>Let&#8217;s start by creating a new google spread sheet. Selecting &#8220;Script Editor&#8221; from the top menu, will open a new tab with a sort of IDE for writing g-drive scripts.</p>
<p><img loading="lazy" data-attachment-id="57" data-permalink="https://fishtrone.wordpress.com/2019/05/14/connecting-unity-editor-to-google-sheets/new-project-6/" data-orig-file="https://fishtrone.files.wordpress.com/2019/05/new-project-6.png" data-orig-size="451,207" data-comments-opened="1" data-image-meta="{&quot;aperture&quot;:&quot;0&quot;,&quot;credit&quot;:&quot;&quot;,&quot;camera&quot;:&quot;&quot;,&quot;caption&quot;:&quot;&quot;,&quot;created_timestamp&quot;:&quot;0&quot;,&quot;copyright&quot;:&quot;&quot;,&quot;focal_length&quot;:&quot;0&quot;,&quot;iso&quot;:&quot;0&quot;,&quot;shutter_speed&quot;:&quot;0&quot;,&quot;title&quot;:&quot;&quot;,&quot;orientation&quot;:&quot;0&quot;}" data-image-title="New Project (6)" data-image-description="" data-image-caption="" data-medium-file="https://fishtrone.files.wordpress.com/2019/05/new-project-6.png?w=300" data-large-file="https://fishtrone.files.wordpress.com/2019/05/new-project-6.png?w=451" class="alignnone size-full wp-image-57" src="https://fishtrone.files.wordpress.com/2019/05/new-project-6.png?w=451&#038;h=207" alt="New Project (6)" width="451" height="207" srcset="https://fishtrone.files.wordpress.com/2019/05/new-project-6.png 451w, https://fishtrone.files.wordpress.com/2019/05/new-project-6.png?w=150&amp;h=69 150w, https://fishtrone.files.wordpress.com/2019/05/new-project-6.png?w=300&amp;h=138 300w" sizes="(max-width: 451px) 100vw, 451px" /></p>
<p><a href="https://developers.google.com/apps-script/quickstart/custom-functions">The Javascript API </a>allows you to add menu items for custom functions and lots of other things. What we&#8217;ll use is that if you declare a function called <em>doGet() </em>you can listen for web requests.</p>
<p>Here is a script that takes the first 8 values in the spreadsheet and returns them in a JSON format.<!-- HTML generated using hilite.me --></p>
<div style="background:#ffffff;overflow:auto;width:auto;border:solid gray;border-width:.1em .1em .1em .8em;padding:.2em .6em;">
<pre style="margin:0;line-height:125%;"><span style="color:#008800;font-weight:bold;">function</span> doGet(e)
{
  <span style="color:#008800;font-weight:bold;">var</span> result;
  
  <span style="color:#008800;font-weight:bold;">var</span> sheets = SpreadsheetApp.getActiveSheet();
  <span style="color:#008800;font-weight:bold;">var</span> values = [];
  <span style="color:#008800;font-weight:bold;">for</span>( <span style="color:#008800;font-weight:bold;">var</span> i = <span style="color:#0000dd;font-weight:bold;">0</span>; i &lt; <span style="color:#0000dd;font-weight:bold;">8</span>; i++ )
  {
    values.push( sheets.getRange(<span style="color:#0000dd;font-weight:bold;">1</span>+i, <span style="color:#0000dd;font-weight:bold;">1</span>).getValue() );
  }
  
  <span style="color:#008800;font-weight:bold;">var</span> result = {result:values};
  
  
  <span style="color:#008800;font-weight:bold;">var</span> JsonValue = JSON.stringify(result);
  
  <span style="color:#008800;font-weight:bold;">return</span> ContentService.createTextOutput(JsonValue.toString()).setMimeType(ContentService.MimeType.JSON);
}
</pre>
</div>
<p>&nbsp;</p>
<p>Now click Publish/Deploy as web app and choose Who has access to this app &#8211; Anyone, even anonymous. Now you should get an URL that can be used to access this script from the outside. (You might also get a warning about using 3rd party apps).</p>
<p>Now let&#8217;s go to Unity and create a scriptable object to hold our values.<!-- HTML generated using hilite.me --></p>
<div style="background:#ffffff;overflow:auto;width:auto;border:solid gray;border-width:.1em .1em .1em .8em;padding:.2em .6em;">
<pre style="margin:0;line-height:125%;"><span style="color:#336699;">[CreateAssetMenu(fileName="MySO",menuName = "MyScriptableObject")]</span>
<span style="color:#008800;font-weight:bold;">public</span> <span style="color:#008800;font-weight:bold;">class</span> <span style="color:#bb0066;font-weight:bold;">MyScriptableObjectScript</span> : ScriptableObject
{
    <span style="color:#008800;font-weight:bold;">public</span> <span style="color:#888888;font-weight:bold;">int</span>[] Value;
}
</pre>
</div>
<p>&nbsp;</p>
<p>Now with a custom inspector we can actually write the web request, using <em>UnityWebRequest. </em>The only problem is we cannot use a Coroutine to wait for the result, so instead we need to check the state of the request on <em>EditorApplication.update.</em></p>
<div style="background:#ffffff;overflow:auto;width:auto;border:solid gray;border-width:.1em .1em .1em .8em;padding:.2em .6em;">
<pre style="margin:0;line-height:125%;"><span style="color:#336699;">[CustomEditor(typeof(MyScriptableObjectScript))]</span>
<span style="color:#008800;font-weight:bold;">public</span> <span style="color:#008800;font-weight:bold;">class</span> <span style="color:#bb0066;font-weight:bold;">MySOInspector</span> : Editor
{
    <span style="color:#008800;font-weight:bold;">private</span> UnityWebRequest _webRequest;

    <span style="color:#008800;font-weight:bold;">public</span> <span style="color:#008800;font-weight:bold;">override</span> <span style="color:#008800;font-weight:bold;">void</span> <span style="color:#0066bb;font-weight:bold;">OnInspectorGUI</span>()
    {
        DrawDefaultInspector();
        
        <span style="color:#008800;font-weight:bold;">if</span> (GUILayout.Button(<span style="color:#dd2200;background-color:#fff0f0;">"Update from GDrive"</span>))
        {
            _webRequest = UnityWebRequest.Get(YOUR_URL_HERE);
            _webRequest.SendWebRequest();

            EditorApplication.update += CheckForImportRequestEnd; <span style="color:#888888;">// the only way to wait for a process to finish is with this</span>
        }
    }

    <span style="color:#008800;font-weight:bold;">private</span> <span style="color:#008800;font-weight:bold;">class</span> <span style="color:#bb0066;font-weight:bold;">GDocResponse</span> <span style="color:#888888;">// this class is used to parse the JSON</span>
    {
        <span style="color:#008800;font-weight:bold;">public</span> <span style="color:#888888;font-weight:bold;">int</span>[] result;
    }
    
    <span style="color:#008800;font-weight:bold;">private</span> <span style="color:#008800;font-weight:bold;">void</span> <span style="color:#0066bb;font-weight:bold;">CheckForImportRequestEnd</span>()
    {
        <span style="color:#008800;font-weight:bold;">if</span> (_webRequest != <span style="color:#008800;font-weight:bold;">null</span> &amp;&amp; _webRequest.isDone)
        {
            <span style="color:#888888;font-weight:bold;">var</span> result = JsonUtility.FromJson&lt;GDocResponse&gt;(_webRequest.downloadHandler.text);
            MyScriptableObjectScript myTarget = (MyScriptableObjectScript)target;
            myTarget.Value = result.result;
            EditorApplication.update -= CheckForImportRequestEnd;
            Repaint();
        }
    }
}
</pre>
</div>
<p>&nbsp;</p>
<p>And that&#8217;s it. After pressing the button in the inspector, you should see the first 8 values from your google spreadsheet.</p>
<blockquote><p>If you edit the spreadsheet script, make sure to publish it with a higher version number. Otherwise the changes won&#8217;t show when you call the URL.</p></blockquote>
<p>The reverse &#8211; sending data from Unity to the spreadsheet &#8211; can be done using the <em>doPost</em> method with one argument and reading the incoming data from it. On Unity side, use the <em>UnityWebRequest.Post</em> method.</p>
<p>All source code can be found here: <a href="https://github.com/randalfien/unity-editor-scripting-tips" target="_blank" rel="noopener">github.com/randalfien/unity-editor-scripting-tips</a></p>
<p>This is a second blog post in a series on editor scripting, check out the <a href="https://fishtrone.wordpress.com/2019/05/11/custom-unity-inspectors-and-conditional-compilation/">first part here</a>.</p>
]]></html><thumbnail_url><![CDATA[https://fishtrone.files.wordpress.com/2019/05/new-project-6.png?fit=440%2C330]]></thumbnail_url><thumbnail_width><![CDATA[440]]></thumbnail_width><thumbnail_height><![CDATA[202]]></thumbnail_height></oembed>