- Home /
how can I rotate object reading from excel data & time steps
Hey guys, I could really use some help here ( I apologize for being a noob in advance :| . Kinda new to Unity scripting and have a basic understanding of programming). Thanks for help in advance.
I'm trying to right a script ( C# preferably, but java can help) to grab data from excel. This data is pretty much feeds angles of an object that rotates about the x axis. I need the object to rotate smoothly to those degrees. Think of something oscillating to the left, back, then to the right using these angles per time step.
When I do a test code with transform.rotate , it keeps rotating an my object continuously. I even looked into euler angles and that's slightly over my head. Anyways, I including a schematic and a sample excel table within the zip consisting of an angle of interest, the current angle, and incremental change....
using UnityEngine; using System.Collections;
public class Rotate Barge : MonoBehaviour {
// Use this for initialization
void Start () {
}
// Update is called once per frame
void Update () {
transform.rotate(0,0,0);
//transform.rotate(1,0,0);
//transform.rotate(2,0,0);
}
}
It would help if you explained what you are actually trying to do for the game, otherwise this question is about Excel and not related to Unity. Basically, I see you simply linearly rocking a "barge" back and forth, which can be done straight in code. Besides, your Excel data will always be split into time steps that may not necessarily match that of your game's. Is Excel a requirement here?
Export the excel data into a comma separated file. The load the csv as a text asset, and read the values line by line. If it's mission critical that your Unity app reads from Excel, then you are going to need to learn how to do that - I doubt many people on this community site have done that before.
Guys, thanks alot for you help and direction. I really appreciate it. Again, new to Unity and code integrating. Unfortunately my experience coding involves vba for Inventor. Some little c++ experience.
@ $$anonymous$$TheDev- Excel here is not necessary mission critical. Pretty much, we have test data of an object floating in water in excel recorded over time. The physical data consist of the rocking motion ( data from left to right in angles) rotationg about the x-axis and a bobbing motion up and down translating along the vertical axis. We're using Unity for a simple simulation. I know it sounds a bit trivial.
@Graham Dunnett-A co-worker mentioned CSV being more efficient too. I messed around with the curve animatator today to get a feel for it. Pretty slick.
Let me try to simplify this. At a particular time step, I would just like to apply a rotate transform lineraly within the animator segment ( about the x-axis) from a csv file. That animation can be looped. Not gonna lie, don't even know where to begin the scripting here.
Time,"Angle-X","Trans-X", 0.0, 0.0, 0.0, 0.5, 3.0, 3.0, 1.0, 5.0, 3.5, 1.5, 1.0, 2.5, 2.0. -2.5, 1.0,
I appreciate any help whatsoever. Thanks you.
Answer by DerWoDaSo · Feb 18, 2014 at 01:17 PM
I would also use CSV files instead of Excel files, the way Graham mentioned in the comment.
Smooth interpolation could easily be done by creating an animation curve from script and adding these values from the CSV as keyframes.
Answer by robertbu · Feb 19, 2014 at 01:20 AM
for @DerWoDaSo's suggestion of using an AnimationCurve. When I looked at your question yesterday, I saw a messy waypoint-like solution, but an AnimationCurve makes things simple. I'd written CSV parsing code as an answer a couple of days ago and wanted to see what your rocking data would look like when played. So here is a class that will read in a CSV file of your Excel data and rocks the game object on the X axis. Note if you are going to have other rotations, you will need to either split this rotation off to use its own game object or combine that code into this class.
using UnityEngine; using System.Collections;
public class RockTheBoat : MonoBehaviour {
private AnimationCurve ac = new AnimationCurve(); private float maxTime; void Start() { LoadData("e:/data.csv"); StartCoroutine(DoTheRocking(true)); } private void LoadData(string filePath) { string input = System.IO.File.ReadAllText (filePath); string[] lines = input.Split (new[] { '\r', '\n' }, System.StringSplitOptions.RemoveEmptyEntries); for (int i = 0; i < lines.Length; i++) { string[] nums = lines[i].Split(new[] { ',' }); if (nums.Length < 2) { Debug.Log ("Misforned input on line "+i+1); } float timestamp; float angle; if (float.TryParse (nums[0], out timestamp)) { if (float.TryParse (nums[1], out angle)) { ac.AddKey (timestamp, angle); if (timestamp > maxTime) maxTime = timestamp; } } } } private IEnumerator DoTheRocking(bool repeat) { do { float time = 0.0f; while (time <= maxTime) { transform.eulerAngles = new Vector3(ac.Evaluate (time), 0.0f, 0.0f); yield return null; time += Time.deltaTime; } } while (repeat); } }
Can you help me see if I understand this bit of your code correctly?
string input = System.IO.File.ReadAllText (filePath);
// read in a super long string w/ everything in the file
string[] lines = input.Split (new[] { '\r', '\n' }, System.StringSplitOptions.RemoveEmptyEntries);
//Create an array of long strings for each of what would look like rows if you opened the .csv in excel. The seperator is basically when the data ends in the row. new[] creates a new string in the lines array. Lines.length now equals the number of "rows" in the .csv
string[] nums = lines[i].Split(new[] { ',' });
//reads the values of a "row" separated by column 1,2,...
Do I have that right?
Also would it be possible to use LoadData to create an array of values internal to Unity?
Yes, you have this right.
Also would it be possible to use LoadData to create an array of values internal to Unity?
You can use the TextAsset class:
Rename your whatever.csv file to whatever.txt
Drag and drop the text file into the Unity project
Add a public variable at the top of the class 'public TextAsset data'.
Drag and drop the whatever.txt file from within the project on to the 'data' variable in the script (once the script is attached to a game object) in the Inspector.
Then you can use the 'data.text' to access the whole file. The second line in the scrip lines you pulled out would be:
string[] lines = data.text.Split (new[] { '\r', '\n' }, System.StringSplitOptions.RemoveEmptyEntries);
Note an even better solution (which may be beyond what you can do right now), would be to take the code that builds the AnimationCurve and put it in an editor script. Then you could build and save the AnimationCurve and not carry the .csv/.txt in the project at all.
There is an interesting hack that you can do and avoid writing an editor script. Just before you release your app, make the 'ac' variable public:
public AnimationCurve ac;
Then:
Run the app
While the app is running select the game object that has the script above in the hierarchy and copy it to the clipboard.
Stop the app
Paste the game object
Delete the original game object copied
Disable the call to LoadData() in the script
The copied game object will have the AnimationCurve data in the ac variable. You will no longer need the CSV data. You can practice the steps above on what you have now.
string[] lines = input.Split (new[] { '\r', '\n' }, System.StringSplitOptions.RemoveEmptyEntries);
//Create an array of long strings for each of what would look like rows if you opened the .csv in excel. The seperator is basically when the data ends in the row. new[] creates a new string in the lines array. Lines.length now equals the number of "rows" in the .csv
Almost right: The new[] { '\r', '\n' } creates implicitly an array of char's, which are used as "seperator" when splitting the input string. This array is required by the Split function.
One could write more clearly:
char[] splitCharacters = new char[]{ '\r', '\n' };
string[] lines = input.Split(splitCharacters, System.StringSplitOptions.RemoveEmptyEntries);
Answer by OJ3D · Feb 20, 2014 at 10:01 PM
Wooww! @robertbu I owe you a couple brews man, not only did it work but that was really awesome of you . I really appreciate it along with everyones help. I will certainly pay it forward as I come up to speed. Fortunately, I also figured out to add that translation piece along the y.
One last question. Don't know if anyone here has matlab/Simulink experience and linking with Unity3D. Sounds farfetched, but there's an experiement we're trying to do in linking up Matlab/Simulink output data to drive let's say a simulation like the one I proposed but real-time. Don't know if you guys have seen something like this or know someone who has toyed around with this concept.
using UnityEngine; using System.Collections;
public class RockTheBoat : MonoBehaviour {
private AnimationCurve ac = new AnimationCurve();
private AnimationCurve Fac = new AnimationCurve();
private float maxTime;
void Start() {
LoadData("e:/data.csv");
StartCoroutine(DoTheRocking(true));
}
private void LoadData(string filePath) {
string input = System.IO.File.ReadAllText (filePath);
string[] lines = input.Split (new[] { '\r', '\n' }, System.StringSplitOptions.RemoveEmptyEntries);
for (int i = 0; i < lines.Length; i++) {
string[] nums = lines[i].Split(new[] { ',' });
if (nums.Length < 2) {
Debug.Log ("Misforned input on line "+i+1);
}
float timestamp; float anglex; float boby;
if (float.TryParse (nums[0], out timestamp)) { //Go to Colum1, Skip Row1-Start W/Row 2 and apply CSV data per iteration to Anim Key Fram Curves-Time Step
if (float.TryParse (nums[1], out anglex)) { //Go to Colum2, Skip Row1-Start W/Row 2 and apply CSV data per iteration to Anim. curve (ac)-X-Angle Transform
ac.AddKey (timestamp, anglex);
if (float.TryParse (nums[2], out boby)) { //Go to Colum3, Skip Row1-Start W/Row 2 and apply CSV data per iteration to Anim. curve (Fac) -Y-Tranlation Transform
Fac.AddKey (timestamp, boby);
if (timestamp > maxTime)
maxTime = timestamp;
}
}
}
}
}
private IEnumerator DoTheRocking(bool repeat) {
do {
float time = 0.0f;
while (time <= maxTime) {
transform.eulerAngles = new Vector3(ac.Evaluate (time), 0.0f, 0.0f); //Angular Rotate About X-Axis (List)
transform.position= new Vector3 (0.0f,Fac.Evaluate (time),0.0f); //Vertical Translate Along Y-Axis (Heave)
yield return null;
time += Time.deltaTime;
}
} while (repeat);
Glad it worked out.
One last question. Don't know if anyone here has matlab/Simulink experience and linking with Unity3D.
I don't know of anyone. You need to ask this as a new question. Few people are reading this question at this point.
You can use ROS to connect Unity and $$anonymous$$ATLAB/Simulink. I tested successfully.
Your answer
Follow this Question
Related Questions
The name 'Joystick' does not denote a valid type ('not found') 2 Answers
Multiple Cars not working 1 Answer
Using var as a placeholder for velocity... why? 2 Answers
Force to Velocity scaling? 2 Answers
RigidBody Script Conflict 1 Answer