public int[,] position = new int[8, 8];
Figure pawn1 = new Figure();
void Start()
{
pawn1.Create("pawn", 1, new Vector2Int(1, 2));
}
void Update()
{
}
[System.Serializable]
public class Figure
{
public int id;
public void Create(string nameEntered, int IdEntered, Vector2Int positionEntered)
{
position[positionEntered.x, positionEntered.y] = IdEntered;
//CS0120 occurs here
}
}
Getting this error and dont know how to fix it
Is there anyone who´s able to help?
Any kinda help is appreciated
CS0120 means
An object reference is required for the nonstatic field, method, or property 'member'
The reference to
public int[,] position = new int[8, 8];
is non-static or instanced since it doesn't use the keyword static. That means the only way to access it is over the reference of the instance of the outer class.
The solution depends on what you want to do with it:
If you want it non-static so that it is not "shared" between all instances of the outer class a solution could be to pass on your outer classe's instance reference like
private void Start()
{
pawn1.Create("pawn", 1, new Vector2Int(1, 2), this);
}
And in Figure expect according value (replace <OuterType> by the outer classes actual name)
[System.Serializable]
public class Figure
{
public int id;
public void Create(string nameEntered, int IdEntered, Vector2Int positionEntered, <OuterType> reference)
{
reference.position[positionEntered.x, positionEntered.y] = IdEntered;
}
}
Otherwise you can make it static so it is "shared" between all instances of the outer class:
public static int[,] position;
Hint1
If that is all your Create method is supposed to do why not setting the value in the outer class itself?
private void Start()
{
position[1,2] = 1;
// Rather pass on the value in this direction if Figure needs it
pawn1 = new Figure("pawn", position[1,2], /*...*/);
}
Than there is no need to pass position etc on to the Figure instance and than get the value written back (unless there is happening more you didn't show).
Hint2
Instead of create a new Figure in
Figure pawn1 = new Figure();
and than later use its method Create to setup a value you should probably rather use the constructor e.g.:
[System.Serializable]
public class Figure
{
public int id;
public Figure(string nameEntered, int IdEntered, Vector2Int positionEntered, <OuterType> reference)
{
reference.position[positionEntered.x, positionEntered.y] = IdEntered;
}
}
and use it like e.g.
Figure pawn1;
private void Start()
{
pawn1 = new Figure("pawn", 1, new Vector2Int(1, 2), this);
}
Hint3
The usage of Start and Update let's conclude that you are very probably using a MonoBehaviour.
To avoid confusion with the transform.position I'ld recommend to name your field maybe better Positions.
Hint4
So far you are not using any of the Vector2Int's functionality but use it only to get the two int values.
In case you are not doing anything else with positionEntered it would be less overhead to instead of passing on a new Vector2Int only to get two int values simply pass on the int values themselves
pawn1.Create("pawn", 1, 1, 2, this);
and
public void Create(string nameEntered, int IdEntered, int x, int y, <OuterType> reference)
{
reference.position[x, y] = IdEntered;
}
Hint5
In general if you are using MonoBehaviour components but you are not using one of Start or Update etc remove them entirely from your class because Unity calls them as soon as they exist which causes unnecesary overhead.
Related
i was using google's singleton but this must need too many reference.
example, when I have to use another class in my Player class that used singleton, I must be using reference three time. Like this : Player.instance.another.blank=0;
my singleton
public static Player instance;
public void Awake()
{
if(instance ==null){
instance=this;
}
else
{
if(instance!=this){
Destroy(this.gameObject);
}
}
Is there any reason to destroy the instance? Even so, we are not updating the existing instance immediately after destroying it whenever a player is added.
I have a singleton Gist that I usually use: https://gist.github.com/xepherys/34d3d5ce3f44749e8649a25b38127347
It has decent comments for anyone unfamiliar with singletons, and is threadsafe. You can remove everything except the lazy field and the constructor region. I use this as the basis for Manager classes.
using System;
// Update namespace as needed
namespace WhatsYourName
{
/*
This is the name of your threadsafe Singleton - change "SingletonLazyThreadsafe" to value that makes sense, and be sure to use your
editors [Rename] option, or update all values to match.
Just because the Singleton itself is threadsafe does not mean that all methods that might be contained are automatically threadsafe.
If threading is important, use threadsafe variables, such as:
System.Collections.Concurrent.ConcurrentDictionary<TKey,TValue>
https://docs.microsoft.com/en-us/dotnet/api/system.collections.concurrent.concurrentdictionary-2
rather than:
System.Collections.Generic.Dictionary<TKey,TValue>
https://docs.microsoft.com/en-us/dotnet/api/system.collections.generic.dictionary-2
Alternatively, lock() can be used in a pinch, but there is the potential for slight performance hits.
Any field, property, or method not marked with "// REQUIRED" means that it's just a sample and can be removed or changed as needed.
Comments are inline as a reminder and as a point of education for those not familiar with Singletons.
Initial snippet added 12/08/2018 - JSW (Xepherys).
*/
public class SingletonLazyThreadsafe
{
#region Fields
// Private
private static readonly Lazy<SingletonLazyThreadsafe> lazy = new Lazy<SingletonLazyThreadsafe>(() => new SingletonLazyThreadsafe()); // REQUIRED
private int changeCount;
private int myInteger;
private string myString;
// Public
public char MyPublicChar; // Note: Even though it's a field, if it's publicly accessible, I generally capitalize the first letter. This is a personal design choice. Most folk tend to use lowercase for fields regardless of their accessibility level.
#endregion
#region Properties
// Note: Private getter/setter for private field.
private int ChangeCount
{
get
{
return this.changeCount;
}
set
{
this.changeCount = value;
}
}
// Note: Public getter/setter for private field.
public int MyInteger
{
get
{
return this.myInteger;
}
set
{
this.myInteger = value;
}
}
// Note: Public getter / protected setter for private field. This allows a {get} from anywhere, but only a {set} from inside the class or derived classes.
public string MyString
{
get
{
return this.myString;
}
protected set
{
this.myString = value;
}
}
#endregion
#region Constructors
private SingletonLazyThreadsafe() // REQUIRED
{ }
public static SingletonLazyThreadsafe Instance // REQUIRED
{
get
{
return lazy.Value;
}
}
#endregion
#region Methods
// Note: This is a public method that just changes the myInteger field. It's useless since the property is public, but it's just an example. It also call IncreaseCount().
public void IncrementInteger(int value)
{
this.MyInteger = value;
IncreaseCount();
}
// Note: This is a public method that just changes the myString field. It's useless since the property is public, but it's just an example. It also call IncreaseCount().
public void ChangeString(string value)
{
this.MyString = value;
IncreaseCount();
}
// Note: This is a private method, which means it can only be called by other methods in this class, and not publicly or outside of the class. While it could directly change
// 'changeCount', I also have it making changes via the private 'ChangeCount' property, which is also only accessible inside the class.
private void IncreaseCount()
{
this.ChangeCount++;
}
#endregion
}
}
Im trying to do a property drawer for a class that i need to be updated as well as editable from the editor.
If i make the class a monobehaviour the serialisation stops working, but if i remove the monobehaviour inheritance it wont update with the game loop.
Is there any way to have both? I would need the object to be able to instantiate with default (empty) values if a monobehaviour script has non instantiated reference.
[Serializable]
public class MySmallTestProp : MonoBehaviour, ISerializationCallbackReceiver
{
[SerializeField]
private string name;
[SerializeField]
private string _name;
[SerializeField]
private float _someFloat;
public float someFloat;
public MySmallTestProp()
{ }
public void OnBeforeSerialize()
{
_name = name;
}
public void OnAfterDeserialize()
{
name = _name;
}
}
[CustomPropertyDrawer(typeof(MySmallTestProp))]
public class MySmallTestPropPropertyDrawer : PropertyDrawer
{
float rowHeight;
int rowSpacing = 5;
int index;
Rect currentPosition;
public override float GetPropertyHeight(SerializedProperty prop, GUIContent label)
{
rowHeight = base.GetPropertyHeight(prop, label);
var rows = 2;
if (Application.isPlaying)
{
rows++;
}
else
{
rows++;
}
return rowHeight * rows;
}
public override void OnGUI(Rect position, SerializedProperty property, GUIContent label)
{
index = 1;
currentPosition = position;
EditorGUI.BeginProperty(position, label, property);
var nameProp = property.FindPropertyRelative("_name");
EditorGUI.PropertyField(NextPosition(), nameProp, new GUIContent("Name"));
EditorGUI.EndProperty();
}
Rect NextPosition()
{
currentPosition.height = rowHeight;
currentPosition.y = rowSpacing + (rowHeight + rowSpacing) * index++;
return currentPosition;
}
}
So if I understand you correctly what you want to achieve is having a class which is
Serializable
has some default field values
Receives an Update call every frame
Actually I don't think you need any custom property drawer for this.
First two points are as simple as having e.g.
[Serializable]
public class Example
{
// By default this has the value "Default String"
public string someString = "Default String";
// This can be edited only via the Inspector
// by default it is 42
[SerializeField] private float someFloat = 42.0f;
// This is a read-only public access
public float SomeFloat => someFloat;
}
Now to the last and tricky part - the update calls.
The easiest way is to have a dedicated MonoBehaviour like e.g.
public class UpdateDispatcher : MonoBehaviour
{
// Storing the instance for Singleton Pattern
private static UpdateDispatcher _instance;
// Register to this event to receive one call each Update
public static event Action OnUpdate;
// This method is automatically called by Unity when the application is started
// or you enter play mode in the editor
[RuntimeInitializeOnLoadMethod]
private static void Init()
{
// _instsnce is already assigned and alive?
if(_instance) return;
// Otherwise search for one in the scene
_instance = FindObjectOfType<UpdateDispatcher>();
// Found one?
if(_instance) return;
// Otherwise create it now
_instance = new GameObject(nameof(UpdateDispatcher)).AddComponent<UpdateDispatcher>();
}
private void Awake ()
{
// Does another instance already exist?
if(_instance && _instance != this)
{
// Destroy this one
Destroy (gameObject);
return;
}
// Otherwise assign this as the instance and make sure it isn't destroyed when the scene chsnges
_instance = this;
DontDestroyOnLoad (gameObject);
}
private void Update ()
{
// Call the event every frame if something is registered
OnUpdate?.Invoke ();
}
}
And then you can use ISerislizationCallbackReceiver but not for actually doing the serialization (it is already done automatically for the fields) but rather for registration to the update callback like e.g.
[Serializable]
public class Example, ISerializationCallbackReceiver
{
// By default this has the value "Default String"
public string someString = "Default String";
// This can be edited only vis the Inspector
// by default it is 42
[SerializeField] private float someFloat = 42.0f;
// This is a read-only public access
public float SomeFloat => someFloat;
// Nothing to do here, only needed for the interface
public void OnBeforeSerialize() { }
public void OnAfterDeserialize()
{
// Register to the Update event
// It is save to unregister before registering even if we haven't been registered before
// this makes sure we are registered only exactly once
UpdateDispatcher.OnUpdate -= Update;
UpdateDispatcher.OnUpdate += Update;
}
private void Update ()
{
someFloat += Time.deltaTime;
}
}
This answer should be more like a comment, but due to the extension I've decided to post it here.
The objective of a PropertyDrawer is to display properties differently on the editor.
To achieve that you need 2 things:
1.One class that inherits from PropertyAttribute, this will be the reference used in your future scripts.
2.Another class that inherits from PropertyDrawer, here you can type HOW to display the attribute.
One implementation example of a property drawer that shows an attribute without leting the user to edit it from editor:
using UnityEditor;
using UnityEngine;
public class DisplayWithoutEdit : PropertyAttribute
{
}
[CustomPropertyDrawer(typeof(DisplayWithoutEdit))]
public class DisplayWithoutEditDrawer : PropertyDrawer
{
public override float GetPropertyHeight(SerializedProperty property, GUIContent label)
{
return EditorGUI.GetPropertyHeight(property, label, true);
}
public override void OnGUI(Rect position, SerializedProperty property, GUIContent label)
{
GUI.enabled = false;
EditorGUI.PropertyField(position, property, label, true);
GUI.enabled = true;
}
}
Then you can use it on another script doing something like:
[DisplayWithoutEdit] public float randomNumber = 0f;
I have a class in Unity 2017 that only shows some of the public methods in the inspector.
using System.Collections.Generic;
using UnityEngine;
public class Inventory : MonoBehaviour
{
List<ShipPart> _inventory;
int currentInvPosition = 0;
bool invExists = false;
// Use this for initialization
void Start () {
CreateInventory(0, 0);
}
// Show all inventory parts as gameobjects
public void CreateInventory(int quality, int part)
{
...
}
void DestroyInventory()
{
...
}
public void ScrollInvLeft()
{
...
}
public void ScrollInvRight()
{
...
}
void UpdateInv(float offset)
{
...
}
public void AddInventoryItem(ShipPart newShipPart)
{
...
}
public void RemoveInventoryItem(ShipPart oldShipPart)
{
...
}
public void Test1(){}
public void Test2(int i){}
}
I thought it might be because the invisible methods have parameters, so I added the last two methods. However they are visible in the inspector!
I am trying to call the methods from a dropdown UI element, but have also tested from a button and that cant see them either.
What am I doing wrong?
As indicated in the official Unity tutorials, if you want to provide a function to an event in the inspector, the function must meet the following requirements:
The function must be public
The function must have a return type of void
The function must take no or one parameter
If the function takes one parameter, the latter must be one of the following types:
int
float
string
bool
UnityEngine.Object, or any type inheriting from UnityEngine.Object (such as GameObject, MonoBehaviour, ScriptableObject, ...)
public class Arrow : MonoBehaviour {
public virtual void StopArrow(Transform p){
arrowRotation = transform.rotation;
isRelease = false;
rb.velocity = new Vector3(0, 0, 0);
transform.SetParent(p);
transform.rotation = arrowRotation;
}
}
public class ExplosiveArrow : Arrow {
override void StopArrow(Transform p){
base.StopArrow();
}
}
This gives me this error:
Assets/Script/ExplosiveArrow.cs(33,23): error CS0621:
`ExplosiveArrow.StopArrow(Transform)': virtual or abstract members
cannot be private
and
Assets/Script/ExplosiveArrow.cs(33,23): error CS0507:
ExplosiveArrow.StopArrow(UnityEngine.Transform): cannot change
access modifiers when overriding public inherited member
Arrow.StopArrow(UnityEngine.Transform)
Change override void StopArrow(Transform p){ to public override void StopArrow(Transform p){ in your child class and you're done.
Unlike C++, you can't change the access of an overridden method to private if it's marked as public in a parent class.
In C# if you don't declare the access modifiers of the variables and methods in your class, by default they are going to be private.
According Access Modifiers (C# Programming Guide):
The access level for class members and struct members, including
nested classes and structs, is private by default.
So as you can see in your code, Arrow has a public virtual void StopArrow but ExplosiveArrow has a override void StopArrow which by default is the same as private override void StopArrow.
So, if you declare an element as public in a parent class, then you cannot reduce the visibility of that variable/method. If you don't want to expose an element but still you want to be able to access in derived classes you should use protected.
Also...
Assuming only the code you posted, this base.StopArrow(); will also error.
StopArrow() doesn't exist in base class Arrow
You need base.StopArrow(p); there instead.
I am a student who is currently learning Java and trying to write a small text-based RPG game with it. The first problem I encountered in the design of the game is the 'character' class, which represents all the playable heroes and enemy characters, and is now implemented by myself as the following:
class RPGActor {
private String name;
private int HP; // hit points
private int MP; // mana
private int AP; // attack
private int DP; // defense
... // followed by tens of other attributes.
public Actor(int actorID)
{
... // Reads all attributes from a file based on the 'actorID'.
}
public void printStatus()
{
System.out.println(name);
System.out.println("HP :" + HP);
System.out.println("MP :" + MP);
... // And print all the attributes one by one.
}
public void setHP(int newHP)
{
HP = newHP;
}
public int getHP()
{
return HP;
}
public void setMP(...)
{
...
}
// And tens of accessors and mutators for each attribute
}
The problem I see with this design is that there are too many things that needs to be hand-coded: There are some 20-30 attributes in the class, and a separate accessor/mutator needs to be implemented for each of them. And the function for displaying the current status of the hero, printStatus, must output each attribute separately even though every line of output follows the exact same format. This makes the class definition tediously long.
Plus, if later I want to add one more attribute to the game, then I must remember to modify 'printStatus', and add a pair of accessor/mutator for it.
So my question is: is there a way to design the class so that I can use ONE pair of set/get functions to set all attributes. Something like:
public void set(String attribName, int attribVal)
{
...
}
and print the attributes iteratively like this:
public void printStatus()
{
System.out.println(name);
for (...)
System.out.println(curAttribName + ": " + curAttribVal);
}
Thank you very much!
I'll show you a solution, to set all attributes with one method, but you shouldn't use it, I'll tell you the reasons afterwards.
class RPGActor {
private static final String NAME = "Name";
private static final String HP = "HP";
private static final String MP = "MP";
private static final String AP = "AP";
private static final String DP = "DP";
// ... followed by tens of other attributes.
private Map<String, Object> attributes = new HashMap<String, Object>();
public RPGActor(int actorID) {
this.attributes.put(NAME, nameFromFile);
// ... Reads all attributes from a file based on the 'actorID'.
}
public void setAttribute(String attributeName, Object value) {
this.attributes.put(attributeName, value);
}
public int getAttribute(String attributeName) {
return this.attributes.get(attributeName);
}
}
This has several disadvantages:
no code-completion for setting specific attributes
less readable
...
BETTER:
Although you are using classes and objects, this isn't very object-oriented. Especially you're violating the encapsulation paradigm.
You shouldn't set the HP explicitly from outside the class itself. Only in rare use cases that is needed. Instead you should think about what the actor really does: attacking, defending, casting spells.
Therefore it should look more like this:
class RPGActor {
private String name;
private int HP; // hit points
private int MP; // mana
private int AP; // attack
private int DP; // defense
// ... followed by tens of other attributes.
private Map<String, Object> attributes = new HashMap<String, Object>();
public RPGActor(int actorID) {
// ... Reads all attributes from a file based on the 'actorID'.
}
public void attacks(RPGActor defender) {
defender.defend(this.getAttack());
}
public void defend(Attack attack) {
switch (attack.getType()) {
case PHYSICAL:
// This actor is resistant against physical attacks.
return;
case MAGICAL:
this.HP = this.HP - attack.getStrength();
break;
}
}
public void castSpell(Spell spell, Set<Target> targets) {
// targets could be other actors, equipment or chickens dependent on the spell
// ...
}
}
With inheritance or more advanced design patterns like the Strategy pattern you can make each actor react differently on attacks.