How to create and run animation at runtime? - c#

I'm making a game currently and want to create and run an animation at runtime.
This is what I got so far:
void Start()
{
Sprite[] sprites = upgrades.GetComponent<uprgades>().sprites;
AnimationClip animClip = new AnimationClip();
animClip.frameRate = 60;
EditorCurveBinding spriteBinding = new EditorCurveBinding();
spriteBinding.type = typeof(SpriteRenderer);
spriteBinding.path = "";
spriteBinding.propertyName = "m_Sprite";
ObjectReferenceKeyframe[] spriteKeyFrames = new ObjectReferenceKeyframe[sprites.Length];
for(int j = 0; j < (sprites.Length); j++)
{
spriteKeyFrames[j] = new ObjectReferenceKeyframe();
spriteKeyFrames[j].time = j;
spriteKeyFrames[j].value = sprites[j];
}
AnimationUtility.SetObjectReferenceCurve(animClip, spriteBinding, spriteKeyFrames);
AnimationClipSettings animClipSett = new AnimationClipSettings();
animClipSett.loopTime = true;
animClip.legacy = true; //added
AnimationUtility.SetAnimationClipSettings(animClip, animClipSett);
I don't understand everything completely cause I found this in the internet. But now I need to start the animation. So I did this:
Animation anim = someGameObject.GetComponent<Animation>();
anim.clip = animClip;
anim.Play();
}
But this doesnt work. I think it has something to do that I don't have any Animator / or Controller but I don't know if I have to add them how and where I should do this

Where are you running the animation? Is it in the update function?

Related

Assignment in Unity script

I want to develop an experimental program in unity. In the program, I use scripts to create a series of objects and assign values to them. I use Tobii's SDK to develop an eye movement experimental program. In order to get the line of sight feedback of these objects (actually a ray collision detection principle), I created a script and added this script for each object. But when I run, I find that only the last of the series of objects I create will give correct feedback, and the other objects will not give feedback。
My feedback script is as follow:
void Update () {
if (_gazeAwareComponent.HasGazeFocus) {
img.color = _outColor;
newText = textName.text;
MainInteraction.isEnter = true;
} else {
img.color = initinalColor;
newText = null;
MainInteraction.isEnter = false;
}
}
I use a static variable to control the state of feedback.
And in my main script, my fuction is:
void createTargetAndText (int number) {
int[] a = GetRandomSequence(10, currentTrailTime);
for (int i = 0; i < number; i++) {
GameObject image = new GameObject();
image.transform.localScale = Vector3.one;
image.name = a[i].ToString();
image.AddComponent<Image>();
image.AddComponent<SphereCollider>();
image.GetComponent<SphereCollider>().radius = targetSize / 2;
image.AddComponent<Feedback>();
image.GetComponent<Image>().sprite = sourceImage;
image.transform.SetParent(currentGameObject.transform.GetChild(3).transform);
image.layer = LayerMask.NameToLayer("UI");
GameObject textGame = new GameObject();
textGame.name = a[i].ToString();
textGame.AddComponent<Text>();
textGame.GetComponent<Text>().font = textFont;
textGame.GetComponent<Text>().text = textGame.name;
textGame.GetComponent<Text>().fontSize = 48;
textGame.GetComponent<Text>().alignment = TextAnchor.MiddleCenter;
textGame.GetComponent<Text>().color = Color.black;
textGame.transform.SetParent(image.transform);
textGame.layer = LayerMask.NameToLayer("UI");
}
}
The only problem is MainInteration.isEnter doesn't work, when I try to change the color to debug, it works.
if (_gazeAwareComponent.HasGazeFocus) {
img.color = _outColor;
newText = textName.text;
MainInteraction.isEnter = true;
if (this.name == "2") {
MainInteraction.isEnter = true;
img.color = Color.cyan;
}
}
I guess the problem may come from:
the static variables in Unity.
Can someone help me answer it? Thank you

How can I return from a method also List of transforms or gameobjects without making instances fro new gameobjects?

using UnityEngine;
using System.Collections;
using System.Collections.Generic;
using System.IO;
using UnityEngine.SceneManagement;
public static class TransformSaver
{
[System.Serializable]
public class TransformInfo
{
public string sceneName;
public string name;
public Transform parent;
public Vector3 pos;
public Quaternion rot;
public Vector3 scale;
}
//Save Transform
public static void SaveTransform(Transform[] tranformToSave)
{
TransformInfo[] trnfrm = new TransformInfo[tranformToSave.Length];
for (int i = 0; i < trnfrm.Length; i++)
{
trnfrm[i] = new TransformInfo();
trnfrm[i].sceneName = tranformToSave[i].gameObject.scene.name;
trnfrm[i].name = tranformToSave[i].name;
trnfrm[i].parent = tranformToSave[i].parent;
trnfrm[i].pos = tranformToSave[i].localPosition;
trnfrm[i].rot = tranformToSave[i].localRotation;
trnfrm[i].scale = tranformToSave[i].localScale;
}
string jsonTransform = JsonHelper.ToJson(trnfrm, true);
File.WriteAllText(#"d:\json\json.txt", jsonTransform);
}
//Load Transform
public static Transform[] LoadTransform()
{
string jsonTransform = File.ReadAllText(#"d:\json\json.txt");
if (jsonTransform == null)
{
return null;
}
TransformInfo[] savedTransforms = JsonHelper.FromJson<TransformInfo>(jsonTransform);
GameObject[] gameObjects = new GameObject[savedTransforms.Length];
Transform[] loadedTransforms = new Transform[savedTransforms.Length];
for (int i = 0; i < gameObjects.Length; i++)
{
SceneManager.SetActiveScene(SceneManager.GetSceneByName(savedTransforms[i].sceneName));
gameObjects[i] = new GameObject();
loadedTransforms[i] = gameObjects[i].transform;
loadedTransforms[i].name = savedTransforms[i].name;
loadedTransforms[i].parent = savedTransforms[i].parent;
loadedTransforms[i].localPosition = savedTransforms[i].pos;
loadedTransforms[i].localRotation = savedTransforms[i].rot;
loadedTransforms[i].localScale = savedTransforms[i].scale;
}
return loadedTransforms;
}
}
The problem is that the method LoadTransform will return array of Transforms but also will create new GameObjects in the Editor in the Hierarchy.
What I want to do is to add something like a boolean flag or maybe other way so I can select if toe return the array of transforms with or without creating new gameobjects so I tried something like that:
//Load Transform
public static Transform[] LoadTransform(bool returnInfo)
{
string jsonTransform = File.ReadAllText(#"d:\json\json.txt");
if (jsonTransform == null)
{
return null;
}
TransformInfo[] savedTransforms = JsonHelper.FromJson<TransformInfo>(jsonTransform);
GameObject[] gameObjects = new GameObject[savedTransforms.Length];
Transform[] loadedTransforms = new Transform[savedTransforms.Length];
for (int i = 0; i < gameObjects.Length; i++)
{
SceneManager.SetActiveScene(SceneManager.GetSceneByName(savedTransforms[i].sceneName));
if (returnInfo == true)
{
gameObjects[i] = new GameObject();
loadedTransforms[i] = gameObjects[i].transform;
}
loadedTransforms[i].name = savedTransforms[i].name;
loadedTransforms[i].parent = savedTransforms[i].parent;
loadedTransforms[i].localPosition = savedTransforms[i].pos;
loadedTransforms[i].localRotation = savedTransforms[i].rot;
loadedTransforms[i].localScale = savedTransforms[i].scale;
}
return loadedTransforms;
}
I added a bool flag returnInfo but now loadedTransforms is null.
But the main goal is to decide if to return array of transforms with or without making instances for new gameobjects.
The problem is when I'm using Editorwindow type script and inside OnGUI to save and load the objects:
List<GameObject> selections = Selection.objects.OfType<GameObject>().ToList();
if (selections.Count > 0)
{
GUI.enabled = true;
}
else
{
GUI.enabled = false;
}
if (GUILayout.Button("Save selected objects data"))
{
if (selections.Count > 0)
{
tempTransformSelection = selections;
for (var i = selections.Count - 1; i >= 0; --i)
{
var selected = selections[i];
transformSelection.Add(selected.transform);
}
TransformSaver.SaveTransform(transformSelection.ToArray());
transformSelection = new List<Transform>();
}
}
var file = #"d:\json\json.txt";
FileInfo fi = new FileInfo(file);
// By default asume you don't want to show the button
// it will than only be enabled if the later conditions match
bool showButton = false;
// you can check this already here not in the loop
// if no file -> nothing to do
if (!File.Exists(#"d:\json\json.txt") || fi.Length <= 0) return;
// This is only reached if the file exists and is not empty
// check for null transforms
for (int i = 0; i < tempTransformSelection.Count(); i++)
{
// if not null do nothing
if (tempTransformSelection[i] != null)
continue;
// otherwise enable the button and leave the loop
showButton = true;
break;
}
// if not true then button won't be shown
if (showButton == true)
{
GUI.enabled = true;
}
else
{
GUI.enabled = false;
}
if (GUILayout.Button("Instantiate back deleted selected bojects"))
{
TransformSaver.LoadTransform(true);
showButton = false;
}
}
private void OnInspectorUpdate()
{
Repaint();
}
The main goal is to select objects in the hierachy in the editor. Then to click on "Save selected objects data" to save the selected object to a json file.
Then I want to make that only if one of the saved objects to the file is null in the hierarchy fro example if I deleted one or more of the objects in the saved file ! only then enable true the button "Instantiate back deleted selected bojects"
And then when clicking on the button "Instantiate back deleted selected bojects" set the button back to enabled false !
But the important thing is to check for null against the saved list of objects in the json file ! But once again I'm stuck with the tempTransformSelection and with how to enable false/true the button.

how to set drawabletop programmatically in xamarin android?

I am trying to create a button in Xamarin android with an image above it. doing some googling i found that there is something in the axml u can use called drawabletop. however my buttons are created programmatically, so in want to know how i can fill in this parameter outside of the axml. button.drawabletop does not exist.
private async void LoadCardList(string code)
{
CardDataService cardDataService = new CardDataService(new CardRepo());
Cards = await cardDataService.GetCardsAsync(code);
TableLayout ll = View.FindViewById<TableLayout>(Resource.Id.cardlist);
TableRow.LayoutParams lp = new TableRow.LayoutParams(LinearLayout.LayoutParams.MatchParent, LinearLayout.LayoutParams.MatchParent);
var i = 0;
var row = new TableRow(this.Activity);
row.WeightSum = 2;
var sortedCards = Cards.OrderBy(o => o.number).ToList();
foreach (var cards1 in sortedCards)
{
var b = new Button(this.Activity);
b.Text = cards1.name;
lp.Weight = 1;
b.LayoutParameters = lp;
row.AddView(b);
i++;
if (i > 1)
{
ll.AddView(row, new TableLayout.LayoutParams(TableLayout.LayoutParams.MatchParent, TableLayout.LayoutParams.WrapContent));
row = new TableRow(this.Activity);
row.LayoutParameters = lp;
i = 0;
}
}
this is my method where i do everything. those buttons i create are the ones i want to have an image. the sortedCards list also contains an image.
regards,
Bjorn
Try
b.SetCompoundDrawables(left, top, right, bottom);
or
b.SetCompoundDrawablesWithIntrinsicBounds(left, top, right, bottom);
as mentioned here:
How to set property "android:drawableTop" of a button at runtime

ZedGraph - How to change X-axis from points to time?

i have a working DLL where i have one function to add arrays to a list and another function that shows all list-arrays in a ZED-Graph-diagram. All arrays have the same size.
Currently the x-axis is shown in points from 0 to 1024.
Question is: What do i have to change to display the x-axis in time?
I have the value "Intervall" (time between two points) that i can pass into the function.
Thanks for the help.
Here is what i have so far:
public void AddGraph(double[] Values, string LegendName)
{
int i = 0;
PointPairList list = new PointPairList();
for (i = 0; i < Values.Length; i++)
{
list.Add(i, Values[i]);
}
if (i > MaxXAxis)
MaxXAxis = i;
SList.Add(list);
SListColor.Add(Color.Black);
SListName.Add(LegendName);
}
public void ShowDiagram(string Title, string XAxisName, string YAxisName, int Timeout_ms)
{
ZedGraph.ZedGraphControl zgc = new ZedGraphControl();
GraphPane myPane = zgc.GraphPane;
LineItem myCurve = null;
// Set the titles and axis labels
myPane.Title.Text = Title;
myPane.XAxis.Title.Text = XAxisName;
myPane.YAxis.Title.Text = YAxisName;
for (int i = 0; i < SList.Count(); i++)
{
myCurve = myPane.AddCurve(SListName[i], SList[i], SListColor[i], SymbolType.None);
myCurve.Line.Width = 2;
}
// Add gridlines to the plot, and make them gray
myPane.XAxis.MinorGrid.IsVisible = true;
myPane.YAxis.MinorGrid.IsVisible = true;
myPane.XAxis.MinorGrid.Color = Color.LightGray;
myPane.YAxis.MinorGrid.Color = Color.LightGray;
myPane.XAxis.MinorGrid.DashOff = 0;
myPane.YAxis.MinorGrid.DashOff = 0;
myPane.XAxis.MajorGrid.IsVisible = true;
myPane.YAxis.MajorGrid.IsVisible = true;
myPane.XAxis.MajorGrid.Color = Color.Gray;
myPane.YAxis.MajorGrid.Color = Color.Gray;
myPane.XAxis.MajorGrid.DashOff = 0;
myPane.YAxis.MajorGrid.DashOff = 0;
// Move Legend to buttom
myPane.Legend.Position = LegendPos.Bottom;
zgc.AxisChange();
myPane.XAxis.Scale.Max = MaxXAxis;
zgc.Location = new Point(0, 0);
zgc.Size = new Size(panel_diagramm.ClientRectangle.Width, panel_diagramm.ClientRectangle.Height);
panel_diagramm.Controls.Add(zgc);
}
This is my first time posting so I apologize for not putting it in a better format.
The following allows you to setup your x-axis to display time:
myPane.XAxis.Type = AxisType.Date;
myPane.XAxis.Title.Text = "Time (HH:MM:SS)";
myPane.XAxis.Scale.Format = "HH:mm:ss";
myPane.XAxis.Scale.MajorUnit = DateUnit.Minute;
myPane.XAxis.Scale.MinorUnit = DateUnit.Minute;
myPane.XAxis.Scale.Min = DateTime.Now.Subtract(new TimeSpan(0, 0, 10, 0, 0).ToOADate();
myPane.XAxis.Scale.Max = DateTime.Now.ToOADate();

how to increase speed of tchart refresh()?

I have 16 graphs[maximum ] with 4 fastlines in each graph. In each graph 3 fastlines represent min , max and ideal value. 4th fastline is actual values from the hardware. I have to run the test for 18,000 samples. So , first 3 fastlines are already drawn and when the switch is on and data comes in , 4th fastline is drawn. In order to draw the 4th line, I use the method Series4.Add(actualvalue, "" , color.red) .
here is the problem. each time the sample is drawn on 4th line. chart has to be refreshed in order to view the plotting of that sample. that also redraws the other 3 fastlines with 18,000 samples in each . so it redraws that many samples without use again and again. I need to draw only 4th fastline.
I can not use an array to fill the values up and then assign it as a source of fastline because I dont have any values beforehand. I tried series4.repaint() method and series4.refreshseries() method, but that doesnt repaint 4th series actually. we have to refresh the whole chart.
and therefore, it slows down the performance because of high number of samples in each fastline [18,000] and one graph with 4 fastlines and total 16 graphs like this.
I ve already done
Series4.AutoRepaint = false, Series4.DrawAllPoints = false;
Series4.XValues.Order = ValueListOrder.None , Series4.YValues.Order = ValueListOrder.None
Is there any way I can increase the performance ?
Thank you.
I have made a simple code, where I have added 4 charts with 4 FastLines with 18000 points for each fastline using a table to add a initialize values and after I update only the values of Series4. The performance is good for the number of values I am drawing:
public Form1()
{
InitializeComponent();
InitializeChart();
}
// Steema.TeeChart.Styles.FastLine Series1;
Timer timer1, timer2,timer3, timer4;
Random r;
DateTime dt;
DateTime[] Xvalues1;
double[] Yvalues1;
Steema.TeeChart.TChart tChart1, tChart2, tChart3,tChart4;
private void InitializeChart()
{
tChart1 = new TChart();
tChart2 = new TChart();
tChart3 = new TChart();
tChart4 = new TChart();
this.Controls.Add(tChart1);
this.Controls.Add(tChart2);
this.Controls.Add(tChart3);
this.Controls.Add(tChart4);
//Initialize Locations and size
this.Width = 908;
this.Height = 600;
//Location
tChart1.Left = 12;
tChart1.Top = 53;
tChart2.Left = 468;
tChart2.Top = 53;
tChart3.Left = 12;
tChart3.Top = 318;
tChart4.Left = 468;
tChart4.Top = 318;
//Size
tChart1.Width = 373;
tChart1.Height = 236;
tChart2.Width = 373;
tChart2.Height = 236;
tChart3.Width = 373;
tChart3.Height = 236;
tChart4.Width = 373;
tChart4.Height = 236;
tChart1.Aspect.View3D = false;
tChart2.Aspect.View3D = false;
tChart3.Aspect.View3D = false;
tChart4.Aspect.View3D = false;
tChart1.Legend.Visible = false;
tChart2.Legend.Visible = false;
tChart3.Legend.Visible = false;
tChart4.Legend.Visible = false;
tChart1.Panel.Gradient.Visible = false;
tChart2.Panel.Gradient.Visible = false;
tChart3.Panel.Gradient.Visible = false;
tChart4.Panel.Gradient.Visible = false;
tChart1.Axes.Bottom.AxisPen.Visible = false;
tChart2.Axes.Bottom.AxisPen.Visible = false;
tChart3.Axes.Bottom.AxisPen.Visible = false;
tChart4.Axes.Bottom.AxisPen.Visible = false;
tChart1.Axes.Left.AxisPen.Visible = false;
tChart2.Axes.Left.AxisPen.Visible = false;
tChart3.Axes.Left.AxisPen.Visible = false;
tChart4.Axes.Left.AxisPen.Visible = false;
//Series
tChart1.AutoRepaint = false;
tChart2.AutoRepaint = false;
tChart3.AutoRepaint = false;
tChart4.AutoRepaint = false;
for (int i = 0; i < 4; i++)
{
new Steema.TeeChart.Styles.FastLine(tChart1.Chart);
new Steema.TeeChart.Styles.FastLine(tChart2.Chart);
new Steema.TeeChart.Styles.FastLine(tChart3.Chart);
new Steema.TeeChart.Styles.FastLine(tChart4.Chart);
tChart1[i].XValues.DateTime=true;
tChart2[i].XValues.DateTime = true;
tChart3[i].XValues.DateTime = true;
tChart4[i].XValues.DateTime = true;
InitialDataSeries(tChart1[i]);
InitialDataSeries(tChart2[i]);
InitialDataSeries(tChart3[i]);
InitialDataSeries(tChart4[i]);
}
//Axes labels
tChart1.Axes.Bottom.Labels.DateTimeFormat = "dd/MM";
tChart1.Axes.Bottom.Labels.Angle = 90;
tChart2.Axes.Bottom.Labels.DateTimeFormat = "dd/MM";
tChart2.Axes.Bottom.Labels.Angle = 90;
tChart3.Axes.Bottom.Labels.DateTimeFormat = "dd/MM";
tChart3.Axes.Bottom.Labels.Angle = 90;
tChart4.Axes.Bottom.Labels.DateTimeFormat = "dd/MM";
tChart4.Axes.Bottom.Labels.Angle = 90;
tChart1.AutoRepaint = true;
tChart2.AutoRepaint = true;
tChart3.AutoRepaint = true;
tChart4.AutoRepaint = true;
tChart1.Refresh();
tChart2.Refresh();
tChart3.Refresh();
tChart4.Refresh();
//Timer
timer1 = new Timer();
timer1.Start();
timer1.Interval = 100;
timer1.Tick += new EventHandler(timer1_Tick);
}
void timer1_Tick(object sender, EventArgs e)
{
//See the chart data updated.
tChart1[0].Visible = false;
tChart1[1].Visible = false;
tChart1[2].Visible = false;
PopulateSeries(tChart1[3]);
PopulateSeries(tChart2[3]);
PopulateSeries(tChart3[3]);
PopulateSeries(tChart4[3]);
}
private void PopulateSeries(Steema.TeeChart.Styles.Series Series1)
{
r = new Random();
dt = DateTime.Now;
tChart1.AutoRepaint = false;
tChart2.AutoRepaint = false;
tChart3.AutoRepaint = false;
tChart4.AutoRepaint = false;
// show only 50 points - delete the rest
while (Series1.Count > 10000)
{
Series1.Delete(0);
}
if (Series1.Count > 10000)
{
Series1.Delete(0);
}
else
{
for (int t = 0; t < 100; t++)
{
Series1.Add(dt, r.Next(1000));
dt = dt.AddSeconds(15);
}
}
tChart1.AutoRepaint = true;
tChart2.AutoRepaint = true;
tChart3.AutoRepaint = true;
tChart4.AutoRepaint = true;
tChart1.Refresh();
tChart2.Refresh();
tChart3.Refresh();
tChart4.Refresh();
}
private void InitialDataSeries(Steema.TeeChart.Styles.Series Series1)
{
//Arrays
dt = DateTime.Now;
r = new Random();
Xvalues1 = new DateTime[18000];
Yvalues1 = new double[18000];
(Series1 as Steema.TeeChart.Styles.FastLine).DrawAllPoints = false;
for (int j = 0; j < 18000; j++)
{
Xvalues1[j] = dt;
dt = dt.AddSeconds(15);
Yvalues1[j] = r.Next(1000);
}
Series1.Add(Xvalues1, Yvalues1);
}
Could you tell us if it help you? On the other hand, if my code doesn't help you I recommend you use TeeChartDirect2D, this is ideal for the high speed data throughput required by DSP realtime applications. See the White paper, Boosting graphics-rendering performance in Windows Forms, for a closer look.
Thanks,

Categories