i try to make a keyboard with lot of btn, and i got "ArgumentException: Object of type 'UnityEngine.Object' cannot be converted to type 'UnityEngine.GameObject'." as the result...
heres my code, can somebody tell the newbie where went wrong...
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
public class a : MonoBehaviour
{
void Start()
{
List<string> btns = new List<string>();
btns.Add("aa"); // aa is the btn name.
foreach (var item in btns)
{
GameObject bo = GameObject.Find(item);
Button btn = bo.GetComponent<Button>();
btn.onClick.AddListener(delegate(){
this.OnClick(bo);
});
}
}
void Update()
{
}
public void OnClick(GameObject sender)
{
Debug.Log("ah");
}
}
i want to press a btn and it'll type the btn's alphebat in a string array.
but when it went wrong i have tried to use Debug.Log() to see where the bug is...
Related
Cannot enter text from class to textbox in form.
We set a keypress event in the MyTreeView class.
The text box cannot contain characters.
What should I do?
*set of textBox1.
*Change Modifiers for textBox1 properties from private to public
*Change keypress event from private to public
*(It didn't work well, so I keep it private now.)
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using System.Diagnostics;
namespace treeview
{
public partial class Form1 : System.Windows.Forms.Form
{
MyTreeView m_tree_view = new MyTreeView();
public Form1()
{
try
{
InitializeComponent();
System.Windows.Forms.TreeNode[] tree1 = new System.Windows.Forms.TreeNode[2];
m_tree_view.Location = new System.Drawing.Point(0, 0);
m_tree_view.Size = ClientSize;
m_tree_view.AllowDrop = true;
tree1[0] = new System.Windows.Forms.TreeNode("TreeNode1");
tree1[1] = new System.Windows.Forms.TreeNode("TreeNode2");
m_tree_view.Nodes.Add("Node1");
Controls.Add(m_tree_view);
}
catch
{
}
}
//This is the code I added.
private void Form1_Load(object sender, EventArgs e)
{
}
}
public class MyTreeView : System.Windows.Forms.TreeView
{
public MyTreeView()
{
try
{
//This is the code I added.
KeyPress += MyTreeView_KeyPress;
}
catch
{
}
}
//This is the code I added.
private void MyTreeView_KeyPress(object sender, System.Windows.Forms.KeyPressEventArgs e)
{
Console.WriteLine("key_press_ok");
//error code↓
//textBox1.Text = "sample";
}
}
}
If you want just to click an button and then print some text i don't understand why you are making another class.
Will be good to make your code efficient and not complicated.
In the main class
private void SendText_Click(object sender, EventArgs e)
{
textBox1.Text = "hi";
}
But if you want to make it complicated and make a class you shuld return i variable and send it to the other class the you can use it.
Learn how to use Public and private first and then use them.
You shuld have a public class which send data and the private to recive and process.
add (Exception ex) to your try catch.
so do:
try
{
// your code
}
catch (Exception ex)
{
MessageBox.Show(ex, "Error in (add where the error is)");
Console.WriteLine(ex);
}
So you will get a detailed Exception Message, maybe it helps you or maybe you will post it here, so we can see what the problem is.
And because you have System.Windows.Forms in your Using Directive
using System.Windows.Forms;
so
System.Windows.Forms.TreeNode[] tree1 = new System.Windows.Forms.TreeNode[2];
is redundant and can be shortened to:
TreeNode[] tree1 = new TreeNode[2];
Error: error CS0103: The name 'JsonConvert' does not exist in the current context
I have the latest Newtonsoft download and I cant figure out any way to fix this I've gone over about 50 different links all saying to install it. Which it is.
Am I missing something small? I am just trying to add my json elements to a list so I can use them in a program and then write back to the Json file. If this cant work can someone link or show me another way to do this in c#?
using System.IO;
using System.Collections.Generic;
using UnityEngine;
using Newtonsoft.Json;
namespace Newtonsoft.Json {
public class CustomControls : MonoBehaviour
{
private List<string> controls;
//public object JsonConvert { get; private set; }
// Start is called before the first frame update
void Start()
{
LoadJson();
for (int i = 0; i < controls.Count; i++)
{
Debug.Log(controls[i].ToString());
}
}
public void LoadJson()
{
using (StreamReader r = new StreamReader("CustomControls.json"))
{
string json = r.ReadToEnd();
controls = JsonConvert.DeserializeObject<List<string>>(json);
}
}
}
}
Change the name of the namespace in your code
using System.IO;
using System.Collections.Generic;
using UnityEngine;
using Newtonsoft.Json;
namespace AnythingOtherThanNewtonsoft.Json {
public class CustomControls : MonoBehaviour
{
private List<string> controls;
//public object JsonConvert { get; private set; }
// Start is called before the first frame update
void Start()
{
LoadJson();
for (int i = 0; i < controls.Count; i++)
{
Debug.Log(controls[i].ToString());
}
}
public void LoadJson()
{
using (StreamReader r = new StreamReader("CustomControls.json"))
{
string json = r.ReadToEnd();
controls = JsonConvert.DeserializeObject<List<string>>(json);
}
}
}
}
If you want or need to use Newtonsoft.Json for some reason, I highly recommend you this guide.
Else, here is an alternative for your case, in which you can use unity`s JsonUtility.
You only need to wrap it in a class
using System.IO;
using UnityEngine;
using System.Collections.Generic;
public class MyControls{
public List<string> controls;
}
public class CustomControls : MonoBehaviour
{
private MyControls myControls;
void Start()
{
SaveJson();
LoadJson();
for (int i = 0; i < myControls.controls.Count; i++)
{
Debug.Log(myControls.controls[i]);//No need to use ToString() here, it`s already a string
}
}
public void SaveJson()
{
MyControls testControls = new MyControls() //Creates a new instance of MyControls
{
controls = new List<string>(2) {"a", "b"} //Your list of strings should go here.
};
File.WriteAllText("CustomControls.json", JsonUtility.ToJson(testControls));
}
public void LoadJson()
{
using (StreamReader r = new StreamReader("CustomControls.json"))
{
string json = r.ReadToEnd();
myControls = JsonUtility.FromJson<MyControls>(json);
}
}
}
Edit: Added an example on how to save a json file using JsonUtility
The file created have this on it {"controls":["a","b"]}
class Program
{
public static string playerName;
static void Main(string[] args)
{
playerName = Console.ReadLine();
}
public static void userInterface()
{
Console.Writeline("Name:" + playerName)
}
}
Been trying to understand where im falling short for a few hours now and cannot figure it out, wondering if any of the SO residents can help me.
Im trying to display a inputted username in a GUI using C# console, I have defined it as a public variable in the class and called it in the method, however its throwing me this exception and displaying a null value?
Any help is appreciated.Class and Main The method im trying to call the variable to
EDIT the desired aim is to have the program display the users inputted username in the UI at the top of the console
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace ConsoleApp1
{
class Program
{
static void Main(string[] args)
{
Player player = new Player
{
Name = "name coming from your input class"
};
UserInterface userInterface = new UserInterface(player);
}
}
class UserInterface
{
public UserInterface(Player player)
{
Console.SetWindowSize(220, 55);
Console.WriteLine("Name: {0}", player.Name);
}
}
class Player
{
public string Name { get; set; }
}
}
Or something alike. So you need to provide values for your variables.
Just call the method userInterface() after this line playerName = Console.ReadLine();
this will display the accepted value on console.
I have an asset saved in my project which represents a serializable scriptable object.
Code of the object is very simple:
using UnityEngine;
using System.Collections;
public class TestScriptable : ScriptableObject {
public float gravity = .3f;
public float plinkingDelay = .1f;
public float storedExecutionDelay = .3f;
}
There is no problem changing values for this object in the inspector, and the changes do persist and survive after exiting → entering Unity.
I am trying to mimic the inspector behavior in an Editor Window. But any changes I do in the Editor Window, though reflected in the Inspector, do not persist.
Here is my two scripts which lay inside the Editor folder:
the first one (auxiliary) - this script replaces inspector fields (see image above) with button, which calls my custom EditorWindow.
using UnityEngine;
using UnityEditor;
[CustomEditor(typeof(TestScriptable))]
public class TestScriptableEditor : Editor {
public override void OnInspectorGUI() {
if (GUILayout.Button("Open TestScriptableEditor"))
TestScriptableEditorWindow.Init();
}
}
the second (with my problem) - script, where I'm trying to change my asset values:
using UnityEngine;
using UnityEditor;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
public class TestScriptableEditorWindow : EditorWindow {
public static TestScriptableEditorWindow testScriptableEditorWindow;
private TestScriptable testScriptable;
[MenuItem("Window/TestTaskIceCat/TestScriptableEditor")]
public static void Init() {
// initialize window, show it, set the properties
testScriptableEditorWindow = GetWindow<TestScriptableEditorWindow>(false, "TestScriptableEditorWindow", true);
testScriptableEditorWindow.Show();
testScriptableEditorWindow.Populate();
}
// initialization of my troubled asset
void Populate() {
Object[] selection = Selection.GetFiltered(typeof(TestScriptable), SelectionMode.Assets);
if (selection.Length > 0) {
if (selection[0] == null)
return;
testScriptable = (TestScriptable)selection[0];
}
}
public void OnGUI() {
if (testScriptable == null) {
/* certain actions if my asset is null */
return;
}
// Here is my tries to change values
testScriptable.gravity = EditorGUILayout.FloatField("Gravity:", testScriptable.gravity);
testScriptable.plinkingDelay = EditorGUILayout.FloatField("Plinking Delay:", testScriptable.plinkingDelay);
testScriptable.storedExecutionDelay = EditorGUILayout.FloatField("Stored Execution Delay:", testScriptable.storedExecutionDelay);
// End of the region of change values
}
void OnSelectionChange() { Populate(); Repaint(); }
void OnEnable() { Populate(); }
void OnFocus() { Populate(); }
}
My questions is: what am I doing wrong? What could be the problem? How to fix it? Am I loading the asset wrongly in the Editor Window? Or what?
Any help/ideas would be appreciated.
Well, everything is simple and complicated, and simple again at the same time.
Despite the visual changes in the inspector - it doesn't mean that the data were actually changed. It looks like everything works fine, but......In my opinion it is shortcoming of the Unity
For correctly work you should use few things:
GUI.changed - returns true if any controls changed the value of the input data. We would be using it for changes detection.
Undo.RecordObject - records any changes done on the object after the RecordObject function. The Undo state is recorded, allowing you to revert the change using the Undo system.
EditorUtility.SetDirty (!!!the most important thing!!!) - shortly: marks target object as "dirty" and therefore requiring a save. For more information - click the link.
Now, all we need to do is to write some code at the bottom of the OnGUI() method;
if (GUI.changed) {
// writing changes of the testScriptable into Undo
Undo.RecordObject(testScriptable, "Test Scriptable Editor Modify");
// mark the testScriptable object as "dirty" and save it
EditorUtility.SetDirty(testScriptable);
}
i.e. your code will be like this:
using UnityEngine;
using UnityEditor;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
public class TestScriptableEditorWindow : EditorWindow {
public static TestScriptableEditorWindow testScriptableEditorWindow;
private TestScriptable testScriptable;
[MenuItem("Window/TestTaskIceCat/TestScriptableEditor")]
public static void Init() {
// initialize window, show it, set the properties
testScriptableEditorWindow = GetWindow<TestScriptableEditorWindow>(false, "TestScriptableEditorWindow", true);
testScriptableEditorWindow.Show();
testScriptableEditorWindow.Populate();
}
// initialization of troubled asset
void Populate() {
Object[] selection = Selection.GetFiltered(typeof(TestScriptable), SelectionMode.Assets);
if (selection.Length > 0) {
if (selection[0] == null)
return;
testScriptable = (TestScriptable)selection[0];
}
}
public void OnGUI() {
if (testScriptable == null) {
/* certain actions if my asset is null */
return;
}
testScriptable.gravity = EditorGUILayout.FloatField("Gravity:", testScriptable.gravity);
testScriptable.plinkingDelay = EditorGUILayout.FloatField("Plinking Delay:", testScriptable.plinkingDelay);
testScriptable.storedExecutionDelay = EditorGUILayout.FloatField("Stored Execution Delay:", testScriptable.storedExecutionDelay);
// Magic of the data saving
if (GUI.changed) {
// writing changes of the testScriptable into Undo
Undo.RecordObject(testScriptable, "Test Scriptable Editor Modify");
// mark the testScriptable object as "dirty" and save it
EditorUtility.SetDirty(testScriptable);
}
}
void OnSelectionChange() { Populate(); Repaint(); }
void OnEnable() { Populate(); }
void OnFocus() { Populate(); }
}
That's all. It was simple and easy.
Now the complicated-simple part of the story...
SetDirty - is certainly good. But this function is due to be deprecated in versions of Unity > 5.3. And also in some versions it will be removed. When? I dont't know.
Instead of using SetDirty you could go another way:
All actions in the custom Editor or EditorWindow you should do between two calls:
serializedObject.Update()
// Here is some of your code
serializedObject.ApplyModifiedProperties()
This code contains:
serializedObject.Update() - Update serialized object's representation
serializedObject.ApplyModifiedProperties() - Apply property modifications.
serializedObject - gets the access to serialized object and gets his properties. SerializedObject is used in conjunction with:
SerializedProperty - get the properties from the serializedObject. All data will be of SerializedProperty type, e.g.
SerializedProperty myGravity = serializedObject.FindProperty("gravity");
SerializedProperty myPlinkingDelay = serializedObject.FindProperty("plinkingDelay");
...
etc.
SerializedObject.FindProperty - Find serialized property by name.
EditorGUILayout.PropertyField - Make a field for SerializedProperty.
The last four is like the SetDirty: they will mark the modified object (or/and scene) as "dirty" and create Undo states for you.
So, knowing that, we could get something like this:
using UnityEngine;
using UnityEditor;
public class TestScriptableEditorWindow : EditorWindow {
public static TestScriptableEditorWindow testScriptableEditorWindow;
private TestScriptable testScriptable;
// declaring our serializable object, that we are working on
private SerializedObject serializedObj;
[MenuItem("Window/TestTaskIceCat/TestScriptableEditor")]
public static void Init() {
testScriptableEditorWindow = GetWindow<TestScriptableEditorWindow>(false, "TestScriptableEditorWindow", true);
testScriptableEditorWindow.Show();
testScriptableEditorWindow.Populate();
}
// initialization of troubled asset
void Populate() {
Object[] selection = Selection.GetFiltered(typeof(TestScriptable), SelectionMode.Assets);
if (selection.Length > 0) {
if (selection[0] == null)
return;
testScriptable = (TestScriptable)selection[0];
// initialization of the serializedObj, that we are working on
serializedObj = new SerializedObject(testScriptable);
}
}
// our manipulation
public void OnGUI() {
if (testScriptable == null) {
/* certain actions if my asset is null */
return;
}
// Starting our manipulation
// We're doing this before property rendering
serializedObj.Update();
// Gets the property of our asset and скуфеу a field with its value
EditorGUILayout.PropertyField(serializedObj.FindProperty("gravity"), new GUIContent("Gravity"), true);
EditorGUILayout.PropertyField(serializedObj.FindProperty("plinkingDelay"), new GUIContent("Plinking Delay"), true);
EditorGUILayout.PropertyField(serializedObj.FindProperty("storedExecutionDelay"), new GUIContent("Stored Execution Delay"), true);
// Apply changes
serializedObj.ApplyModifiedProperties();
}
void OnSelectionChange() { Populate(); Repaint(); }
void OnEnable() { Populate(); }
void OnFocus() { Populate(); }
}
So, it is simple because you should use just
Update → actions → ApplyModifiedProperties.
But it is complicated because you should do a lot of work with bunch of property classes: FindProperty, PropertyField и SerializedProperty.
But when you understand how it works - it is becoming so easy...
I want to get finger positions in Leap motion using c#.I'm new to leap motion controller. So i Couldn't find any example code for detecting finger positions, but i tried to come up with some code. I think it has lot of errors.
So, how to get finger positions in Leap Motion using C#?
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using Leap;
namespace WindowsFormsApplication1
{
public partial class Form1 : Form, ILeapEventDelegate
{
private Controller controller;
private LeapEventListener listener;
public Form1()
{
InitializeComponent();
this.controller = new Controller();
this.listener = new LeapEventListener(this);
controller.AddListener(listener);
}
delegate void LeapEventDelegate(string EventName);
public void LeapEventNotification(string EventName)
{
if (!this.InvokeRequired)
{
switch (EventName)
{
case "onInit":
MessageBox.Show("onInit");
break;
case "onConnect":
MessageBox.Show("onConnect");
break;
case "onFrame":
MessageBox.Show("onFrame");
break;
}
}
else
{
BeginInvoke(new LeapEventDelegate(LeapEventNotification), new object[] {
EventName });
}
}
private void Form1_Load(object sender, EventArgs e)
{
}
}
public interface ILeapEventDelegate
{
void LeapEventNotification(string EventName);
}
public class LeapEventListener : Listener
{
ILeapEventDelegate eventDelegate;
public LeapEventListener(ILeapEventDelegate delegateObject)
{
this.eventDelegate = delegateObject;
}
public override void OnInit(Controller controller)
{
this.eventDelegate.LeapEventNotification("onInit");
}
public override void OnConnect(Controller controller)
{
this.eventDelegate.LeapEventNotification("onConnect");
}
public override void OnFrame(Controller controller)
{
this.eventDelegate.LeapEventNotification("onFrame");
}
public override void OnExit(Controller controller)
{
this.eventDelegate.LeapEventNotification("onExit");
}
public override void OnDisconnect(Controller controller)
{
this.eventDelegate.LeapEventNotification("onDisconnect");
}
}
}
Your code looks like it is derived from the documentation example. However, you have left out the actual event handlers so nothing will ever happen.
You will see in the linked example that there is a newFrameHandler function. You can change that to access the finger positions in the frame object, which is a snapshot of the tracked hands at a moment in time.
void newFrameHandler(Frame frame)
{
foreach(Finger in frame.Fingers){
Vector fingerPosition = finger.TipPosition;
//Do something with this information...
}
}
You can similarly get the hands and then access each hand's fingers, which often is the more natural approach:
foreach(Hand hand in frame.Hands){
foreach(Finger in hand.Fingers){
Vector fingerPosition = finger.TipPosition;
//Do something with this information...
}
}