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.
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
}
}
I need to call a protected variable from a public class into an if statement in a private method of another public class
I am programing a video game in unity and I need to use a bool variable (that shows if the character is out of stamina) in an if statement to determine whether or not the character can run
This is what my code looks like excluding everything unrelated to the problem
Public class CharacterStats : MonoBehaviour
{
[SerialzeField] protected bool Tired;
}
Public class PlayerMovement : MonoBehaviour
{
Private void HandleRunning()
{
If (Input.GetKeyDown(KeyCode.LeftShift) && X != True)
{
Speed = RunSpeed;
}
}
}
X is where I want the Tired variable to be.
Use a public readonly property like e.g.
public class CharacterStats : MonoBehaviour
{
// Keep you serialized field protected
[SerialzeField] protected bool tired;
// Have a public read-only accessor property
public bool Tired => tired;
}
and then e.g.
public class PlayerMovement : MonoBehaviour
{
// Somehow you will need to get a reference to the CharacterStats instance
// e.g. via the Inspector
[SerializeField] private CharacterStats stats;
[SerializeField] private float RunSpeed;
private float Speed;
private void HandleRunning()
{
if (Input.GetKeyDown(KeyCode.LeftShift) && !stats.IsTired)
{
Speed = RunSpeed;
}
}
}
Alternatively (and my apologies to #aybe who had answered this) you can actually directly serialize a property using explicitely
[field: SerializeField] public bool Tired { get; protected set; }
this is a property which can be accessed by everyone but only this and inherited classes (and due to the serialization now the Inspector) have the permission to set the value.
In general: Fix your casing! In c# all keywords are lower key!
I am trying to make a spell system. My base class for the system looks like this:
public abstract class MagicBook : ScriptableObject {
public Sprite bookSprite;
public float manaCost;
public float coolDown;
public bool rapidFire;
[HideInInspector] public bool coolDownElapsed;
public virtual void OnActivate() {
}
public virtual void OnActivate(Vector3 position, Quaternion rotation) {
}
}
Then I have another class extending from MagicBook where I override the OnActivate function. My problem now is that in the inspector only the variable bookSprite is showing and all the other values are not there. I tried adding an [SerializeField] in front of the variables and define them new in the extending class. But they still dont show. Has anyone an idea why they are not showing or how I can fix this?
Thanks for your help and time.
Did you create Asset for ScriptableObject?
Add attribute to extended class:
[CreateAssetMenu(fileName = "Data", menuName = "ScriptableObjects/NewBook", order = 1)]
And then create asset with
Another idea:
Probably you have custom drawer for this object, but...
Turn your inspector into debug mode and check if properties are visible there.
Cannot reproduce this issue with Unity 2020.1.0f1.
public class NewBook : MagicBook
{
}
If an object has a component with a baseclass BaseClass<T>, calling GetComponent<BaseClass<T>>() will not return that component. The generic argument seems to throw it off, as a BaseClass without using generics will correctly return the derived class as a component when GetComponent<BaseClass>() is called.
Does anyone know a solid workaround for this? The use of a generic arg in this class is somewhat important, so I'd obviously rather not re-write the program's class structure just to accommodate this.
Here's a rough sketch of the classes in question
//the base class that I'd like to be able to fetch the subclasses of using GetComponent
public abstract class BaseUIClass<T> : MonoBehaviour where T :BaseEntity {}
//EntityType1&2 are derived from BaseEntity
public class DerivedUIClass1 : BaseUIClass<EntityType1> {}
public class DerivedUIClass2 : BaseUIClass<EntityType2> {}
BaseUIClass has this method:
public virtual void Setup(T entity) {}
Which needs to be called shortly after the component is added to a GO.
EDIT:
Effectively what I'm looking to do is the following, without having to hard-code in (I want to actually make use of the generic args I've defined)
if(uiClassObj is typeof(DerivedUIClass1) go.GetComponent<BaseUIClass<EntityType1>>();
else if(uiClassObj is typeof(DerivedUIClass2) go.GetComponent<BaseUIClass<EntityType2>>();
//etc
But considering that there is a component of type BaseUIClass<BaseEntity> on the go, and the two+ derived classes I'm interested in are defined by DerivedUIClass1<EntityType1> and DerivedUIClass2<EntityType2>, the conversion should surely just be implicit?
You can't do what you want the way you want, because Unity doesn't accept components which are generic classes.
I.E., if you have:
public class MyGenericClass<T> : MonoBehaviour {}
you will not be able to add it as a component unless you specify T via a subclass inheriting from it:
public class MySpecifiedClass : MyGenericClass<[specificType]> {}
So, to solve your problem, you should simply implement a specific interface for everything that should be done when the base class is added as a component. I'll show you an example with float and int derived types, you can extend easily to any type you need.
BaseClass
using UnityEngine;
public interface ISetup {
void CallSetup();
}
public class BaseClass<T> : MonoBehaviour, ISetup {
public T myEntity;
public void CallSetup() {
Setup(myEntity);
}
private void Setup(T entity) {
Debug.Log(entity);
//Your setup code
}
}
Your components classes
public class BaseClassInt : BaseClass<int> {
private void Awake() {
myEntity = 25;
}
}
public class BaseClassFloat : BaseClass<float> {
private void Awake() {
myEntity = 10.6f;
}
}
Code that gets the interface and calls Setup()
var componentsWithSetup = GetComponents<ISetup>();
foreach (var component in componentsWithSetup) {
component.CallSetup();
}
One workaround would be to use a specific type instead of a generic type at the top level for each type that you need the base class for.
For example:
public class SpecificToFirstTypeClass : BaseClass<FirstType>
{
}
and then use GetComponent<SpecificToFirstTypeClass>
Based on a suggestion from this answers.unity.com question
I couldn't believe this didn't work so I hacked it using tags, where UI is a base, abstract class:
public UI currentUI;
public void GetUI()
{
foreach (Transform child in transform)
{
if (child.tag == "UI Canvas")
{
currentUI = child.GetComponent<UI>();
}
}
}
Where I may have a different active "UI" depending on the scene. It might be the main game scene, or the menu scene. Now, I can just interact with the UI manager via generic/abstract methods like LoadUI() or HideUI().
Tbf, this really should be handled by events but it's overkill for my current project.
this is my first question here :)
I know that I should not check for object type but instead use dynamic_cast, but that would not solve my problem.
I have class called Extension and interfaces called IExtendable and IInitializable, IUpdatable, ILoadable, IDrawable (the last four are basicly the same). If Extension implements IExtendable interface, it can extend itself with different Extension objects.
The problem is that I want to allow the Extension which implements IExtendable to extend only with Extension that implements the same interfaces as the original Extension.
You probably don't unerstand that mess so I try to explain it with code:
class IExtendable
{
public:
IExtendable(void);
void AddExtension(Extension*);
void RemoveExtensionByID(unsigned int);
vector<Extension*>* GetExtensionPtr(){return &extensions;};
private:
vector<Extension*> extensions;
};
class IUpdatable
{
public:
IUpdatable(void);
~IUpdatable(void);
virtual void Update();
};
class Extension
{
public:
Extension(void);
virtual ~Extension(void);
void Enable(){enabled=true;};
void Disable(){enabled=false;};
unsigned int GetIndex(){return ID;};
private:
bool enabled;
unsigned int ID;
static unsigned int _indexID;
};
Now imagine the case that I create Extension like this:
class MyExtension : public Extension, public IExtendable, public IUpdatable, public IDrawable
{
public:
MyExtension(void);
virtual ~MyExtension(void);
virtual void AddExtension(Extension*);
virtual void Update();
virtual void Draw();
};
And I want to allow this class to extend itself only with Extensions that implements the same interfaces (or less). For example I want it to be able to take Extension which implements IUpdatable; or both IUpdatable and IDrawable; but e.g. not Extension which implements ILoadable. I want to do this because when e.g. Update() will be called on some Extension which implements IExtendable and IUpdateable, it will be also called on these Extensions which extends this Extension.
So when I'm adding some Extension to Extension which implements IExtendable and some of the IUpdatable, ILoadable... I'm forced to check if Extension that is going to be add implements these interfaces too. So In the IExtendable::AddExtension(Extension*) I would need to do something like this:
void IExtendable::AddExtension(Extension* pEx)
{
bool ok = true;
// check wheather this extension can take pEx
// do this with every interface
if ((*pEx is IUpdatable) && (*this is_not IUpdatable))
ok = false;
if (ok) this->extensions.push_back(pEx);
}
But how? Any ideas what would be the best solution? I don't want to use dynamic_cast and see if it returns null... thanks
You should rethink your design. If you need this behavior, perhaps introduce IUpdateExtendable and IDrawExtendable.
The reason the current approach is bad is that it violates the Liskov Substitution Principle. You're basically saying "this object acts as an IExtendable, but it really doesn't, unless ...." If a class implements an interface, it really should be usable via that interface without any conditions. If it's not, it is a maintenance nightmare waiting to happen.
Just an intuition, but depending on what your extensions are doing, the visitor-pattern might help you. You may also want to read up on the decorator pattern.
I could merge all these interfaces in to one class so I would get something like this:
class Extension
{
public:
Extension(void);
virtual ~Extension(void);
void AddExtension(Extension* pEx){extensions.push_back(pEx);};
virtual void Initialize()
{
for each (Extension* pEx in extensions) pEx->Initialize();
};
virtual void Load()
{
for each (Extension* pEx in extensions) pEx->Load();
};
virtual void Update()
{
for each (Extension* pEx in extensions) pEx->Update();
};
virtual void Draw()
{
for each (Extension* pEx in extensions) pEx->Draw();
};
private:
vector<Extension*> extensions;
};
But this would mean that all of the methods would be called on every added extension. E.g. empty methods in some added extension that doesn't load any content and doesn't draw anything would be called.