- Home /
JesseEtzler's RPG Talent System in C#
Hello, JesseEtzler0 is doing new tutorial series how to make skills. It is pretty easy so far, but I was trying to make it in C# but I failed. Simply, he made a class with variables like skillName, skillDescription etc. and then he made a new script where he made an array of this class properties, like var Skills : skills[] where "skills" is a name of class. Then he just simply defined these skill variables in the inspector. Is there any way how to make it in C#? I tried to make it like this:
using UnityEngine;
public class Skill {
private string _name;
private string _description;
private int _requiredPoints;
private int _addedPoints;
private bool _hasLearnt;
public Skill() {
_name = "Enter name of the skill here.";
_description = "Describe the skill here.";
_requiredPoints = 1;
_addedPoints = 0;
_hasLearnt = false;
}
#region Getters and Setters of Skill class
public string Name {
get { return _name; }
set { _name = value; }
}
public string Description
{
get { return _description; }
set { _description = value; }
}
public int RequiredPoints
{
get { return _requiredPoints; }
set { _requiredPoints = value; }
}
public int AddedPoints
{
get { return _addedPoints; }
set { _addedPoints = value; }
}
public bool HasLearnt
{
get { return _hasLearnt; }
set { _hasLearnt = value; }
}
#endregion
}
And then I made a new script called Skills wherein I was trying to make mentioned array of class, but everything I was trying failed.
Btw, what you are doing with the properties does not really do anything valuable. You might as well make the variable public, same result, faster process.
I read somewhere that variables in class should not be public, so I used getters and setters, if you mean this...
Yes but you should understand why you're doing it. There is no difference between a:
public int x;
and
private int x;
public int X { get { return x; } set { x = value; } }
and
public int X { get; set; } // this is called an auto property, compiler will then turn it to the previous version ^
In all the cases I could come in and set whatever I want.
Why is it bad to make something public? Well, let's say you had a Person
class with an int age
:
public class Person
{
public int age;
}
I could easily come in and:
Person p = new Person();
p.age = -1000;
Does a negative age make any sense to you? No? good, proceed...
To prevent this from happening, make the age private, and wrap it up with a setter:
private int age;
public void SetAge(int value)
{
if (value < 0) // or any type of validation
value = 0;
age = value;
}
Now I can't set a negative age. But what if I wanted to read the age value? I make a getter:
public int GetAge() { return age; }
Ins$$anonymous$$d of writing getters and setters, you use a property:
private int age;
public int Age
{
get { return age; }
set { /*validate*/ age = value; }
}
$$anonymous$$uch cleaner and lesser keystrokes.
If you wanted to have something, that could 'from the outside' only be read, but set by you, you could do:
public int Age { private set; get; }
Everyone could get your Age, but only you can set it.
So the point of Setters is to prevent the outside from doing something to your data you don't want to.
If you don't want any validation, and don't care about the variable's value being messed with, then use a public one.
public int var;
or
public int Var { get; set; }
What if you wanted to have a variable, that you don't want any other class to mess with (set), but they could read it. At the same time, you want it to be visible in the inspector?? You'd do:
[SerializeField] private int myInt;
public int $$anonymous$$yInt { get { return myInt; } }
Thanks, now it is much more clear to me. Damn, if I had these information 1 month ago, when I was looking for it on the internet 2 hours :D.
That's why I always tell people to learn good program$$anonymous$$g before jumping into Unity.
$$anonymous$$ost if not all the tutorials on youtube don't pay any attention to code quality and focuses only on the WOW side of things, just getting the thing over with. This is not good, especially to people with no prior program$$anonymous$$g exp, they'll do what the tutor is doing without any questions regardless of whether it's good or not. When I watch a tutorial series, I don't imitate what the tutor is doing, no matter how good in program$$anonymous$$g he is, that's cause I developed my own style of program$$anonymous$$g, so ins$$anonymous$$d I just take ideas from him and implement them however I see is best.
So watch out, you might get bad habits out of youtube tutorials without you even knowing it.
Answer by vexe · Oct 28, 2013 at 06:57 AM
What do you mean failed?
If this script is supposed to be attached to a game object, you should inherit from MonoBehaviour
and should not set the values yourself in the constructor (unless you want something to always take a default value that the user shouldn't change), and add a [SerializeField]
attribute to the variables you want to make visible in the inspector.
If you don't want to attach this script to a game object and instantiate it normally with new, I suggest you inject the dependencies, instead of hard-coding them in the constructor yourself. In other words, create a constructor like:
public Skill(string name, string description, float points, etc)
Let the outside world, give you what you need.
EDIT: so after some comments, it turned out that you're trying to do something like:
public class Skills : MonoBehaviour
{
Skill Archery = new Skill( stuff );
Archery.Name = "Value";
}
You can't do that in your global space. Do it somewhere like, in Awake or Start or wherever it's relevant to you:
public class Skills : MonoBehaviour
{
Skill Archery;
void Start()
{
Archery = new Skill("Archery", "Allows user to use ranged weapons", 1, 0, false);
Archery.Name = "Archery Skill";
}
}
To be accurate, you could initialize your Skill
member, but you can't set your skill's stuff at the global space. ie you could do:
public class Skills : MonoBehaviour
{
Skill Archery = new Skill("Archery", "Allows user to use ranged weapons", 1, 0, false);
void Start()
{
Archery.Name = "Archery Skill";
}
}
You already have public properties present in your class, you could just use them:
Archery.AddedPoints = 5;
Just look at your code above.
But still I can not work with instantiated class.
I still don't get what you mean.
If you're having trouble with getting the Skill
array visible in the inspector of your game object, when you attach a Skills
script to it, you must add the [SerializeField]
attribute to your skills array, and the [Serializable]
attribute to the Skill
class, like so:
[Serializable]
public class Skill
{
//...
}
Skills.cs
public class Skills : $$anonymous$$onoBheaviour // I would call it Skills$$anonymous$$anager ins$$anonymous$$d of Skills
{
[SerializeField] private Skill[] skills;
}
Now the skills array is visible and you can attach /dragdrop skills.
@$$anonymous$$agnomous if your Skill
class is literally like you commented above, then you removed the properties so you don't have public access to its members. Get the properties back to be able to access stuff, just like you had it originally in your question.
PS: it's nice to keep a constant feedback with the person answering you.
I added [Serializable] above my Skill class, but Visual Studio deosn't know it.
It's located in System
, so either add a using System;
or just explicitly tell it the location: [System.Serializable]
As I told you dude, to access stuff from your Skill
you have to have some public stuff accessible to the outsiders:
public class Skill
{
private string name;
private float whatever;
...
public Skill(string name, float whatever, etc)
{
this.name = name;
this.whatever = whatever;
this.etc = etc;
}
// setters and getters properties, as needed
public float Whatever
{
get { return whatever; }
set
{
whatever = $$anonymous$$athf.Clamp(whatever, $$anonymous$$IN, $$anonymous$$AX); // or something
whatever = value;
}
}
}
Now you can:
Skill skill = new Skill( stuff );
skill.Whatever = someValue;
skill.Name = "mmmmmmmba";
If you want to see your Skill
members in the inspector, Skill
then must be a $$anonymous$$onoBehaviour
. But then, you can't new up a skill, like you used to do before with:
Skill archery = new Skill( stuff );
Cause you can't new up a $$anonymous$$onoBehavoiur
. Ins$$anonymous$$d, now Skill
is a Component, so you add it to your GameObjects, with
Skill archery = myGo.AddComponent<Skill>();
archery.SetStuff ( stuff );
Now, in your Skills
script, to assign the skills array members, you have to have gameObjects in your scene, that has the Skill
script attached to them, then you just drag drop them into your array.
I hope everything's clear now, if not let me know.
Your answer
Follow this Question
Related Questions
Multiple Cars not working 1 Answer
Converting a JS script into C# - hit a wall with arrays... 1 Answer
Distribute terrain in zones 3 Answers
Is this considered bad coding 1 Answer
Translating js to c#, getting NULLReferenceExeption 2 Answers