Good Morning,
I’m building a decorative data visualizer, which uses parsed historical price data from a coingecko api as input to draw the historical price chart as mountain shapes using the line renderer.
Just gonna get out front and say I’m artist and building this with help from ai. Trying my best to learn and understand the code as I go but I know this post is a hot mess so apologies in advance. Sharing as much info that seems related as possible to help provide relevant context. Any information you share will help me learn and be a better programmer.
The project itself is in open alpha testing right now, with lots of random bugs probably related to the canvas and iframe among others (meaning it doesn’t really work on mobile browsers yet) but you can check it out for your self at: Early Days Demo – OrchidxMachina
You’re invited to comment on any bugs you find but I’ll try to keep the scope of this post to one particular problem I’m having:
Specifically, and occasionally, in both Play Mode in the Unity Engine and maybe 1 out of every 20 loading from a browser the line renderer displays the mountain shapes correctly except everything is shifted downwards on the y axis. Restarting play mode or refreshing the browser fixes the problem and the mountains return to their proper position within the camera frame.
I enter playback mode, everything that is instantiated (including gameObjects tied to the same API in another script) are too low in playback.
I then restart play mode (and change nothing else) and everything then works fine.
The only pattern I have seen is that it has happened twice in the Unity Engine now on two separate days first thing after opening the scene. (and then worked for a minute just now and then broke again, but sometimes will go hours without breaking in play mode or browser during testing, without any changes being made to that portion of the game, either way…but also seems to break in play mode 1 out of every 4 times while doing research for this post.)
I tried to make the mountains solid with a mesh but they didn’t fill in. This may be adding to the problem because I learned that, while in play mode, turning the line renderer on/off with checkbox in Inspector turns off a second instantiation of the mountains which sits already outside the frame, then turning mesh on/off turns on and off the mountains which sit inside the frame.
The grey lines are the mesh inside the frame and the orange mesh is the actual points from the line renderer. Rereading the code it is not clear to me why the mesh sits separate from the line renderer itself, nor why the mesh isn’t filled in solid with public material.
Two things to add, which might be unrelated but could be helpful too.
-
Both gameObjects and Line Renderer are generating positions from parsed JSON data with a “floor” gameobject as reference to create the y positions. Regardless as to whether the mountains appear correctly in the frame the floor object is not moving.
-
There is a third script which generates the live price data for the text, which does not share data with the other two scripts, and even though it’s not related to the Line Renderer when it is turned off the Line Renderer breaks and disappears
Here’s the script for the line renderer, partially generated with help from chat-gpt, and i replaced my private api with a generic api for the same data point.
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.Networking;
public class KSM_Hist_Mountains : MonoBehaviour
{
private string URL = "https://api.coingecko.com/api/v3/coins/kusama/market_chart?vs_currency=usd&days=31&interval=daily";
public LineRenderer lineRenderer;
private GameObject floorObject;
public Material mountains;
public float[] ksm_x; // Public x position for KSM historical data, represents time
public float[] ksm_y; // Public y position for KSM historical data, represents price
public float scalingFactor = .00000000005f; // Public scaling factor
void Start()
{
// Find the floor object in the scene, floor object is used as a reference for positioning the line renderer
floorObject = GameObject.FindGameObjectWithTag("floor");
if (floorObject != null)
{
// Start the coroutine to fetch KSM historical data
StartCoroutine(GetKSMHistoricalData());
}
else
{
// Log an error if the floor object is not found
Debug.LogError("Floor object not found!");
}
}
IEnumerator GetKSMHistoricalData()
{
using (UnityWebRequest request = UnityWebRequest.Get(URL))
{
yield return request.SendWebRequest();
if (request.result == UnityWebRequest.Result.ConnectionError)
{
// Log an error if there is a connection error
Debug.LogError(request.error);
}
else
{
// Get the JSON response
string json = request.downloadHandler.text;
Debug.Log(json);
// Parse the JSON data
SimpleJSON.JSONNode data = SimpleJSON.JSON.Parse(json);
SimpleJSON.JSONArray pricesArray = data["prices"].AsArray;
Debug.Log(pricesArray);
// Define the spacing between points, this helps space the points after scaling factor is applied
float spacing = 2f;
// Initialize the arrays
ksm_x = new float[pricesArray.Count + 2];
ksm_y = new float[pricesArray.Count + 2];
// Add the first and last points
ksm_x[0] = floorObject.transform.position.x;
ksm_y[0] = floorObject.transform.position.y;
// Iterate through the prices array and populate the arrays
for (int i = 0; i < pricesArray.Count; i++)
{
// Get the x and y values from the prices array
ksm_x[i + 1] = pricesArray[i][0].AsFloat;
ksm_y[i + 1] = pricesArray[i][1].AsFloat;
// Calculate the position of the line point
Vector3 position = floorObject.transform.position + new Vector3((ksm_x[i + 1] * scalingFactor) + 38f + ((i + 1) * spacing), ksm_y[i + 1] - 20, 0f);
// Set the position of the line point
lineRenderer.positionCount = i + 2;
lineRenderer.SetPosition(i + 1, position);
}
// Add the new point at the end, creating a point to complete the illusion of mountains
ksm_x[ksm_x.Length - 2] = 100f;
ksm_y[ksm_y.Length - 2] = 0f;
// Calculate the position of the new point
Vector3 newPosition = floorObject.transform.position + new Vector3(200f, 0f, 0f);
//the following code is what's generating inside the scene, for good or ill
// Set the position of the new point
lineRenderer.positionCount = ksm_x.Length;
lineRenderer.SetPosition(ksm_x.Length - 2, newPosition);
// Create a mesh to fill the loop of lineRenderer
Mesh mesh = new Mesh();
lineRenderer.BakeMesh(mesh);
// Assign the mountains material to the mesh
MeshRenderer meshRenderer = lineRenderer.gameObject.AddComponent<MeshRenderer>();
meshRenderer.sharedMaterial = mountains;
// Assign the mesh to the mesh filter
MeshFilter meshFilter = lineRenderer.gameObject.AddComponent<MeshFilter>();
meshFilter.mesh = mesh;
}
}
}
}
I’m happy to share the others scripts but don’t know if ya’ll want to see all three or just the one relevant to the line renderer so I’ll hold off on that for now.
Worth adding, obviously, I’m basically a coding noob still.
My apologies if I’m sharing TMI, I know the code’s buggy so maybe the extra info helps. Feel free to comment on any or all of it or none at all.
Thanks,
b


