Wayback Machinekoobas.hobune.stream
May JUN Jul
Previous capture 13 Next capture
2021 2022 2023
1 capture
13 Jun 22 - 13 Jun 22
sparklines
Close Help
  • Products
  • Solutions
  • Made with Unity
  • Learning
  • Support & Services
  • Community
  • Asset Store
  • Get Unity

UNITY ACCOUNT

You need a Unity Account to shop in the Online and Asset Stores, participate in the Unity Community and manage your license portfolio. Login Create account
  • Blog
  • Forums
  • Answers
  • Evangelists
  • User Groups
  • Beta Program
  • Advisory Panel

Navigation

  • Home
  • Products
  • Solutions
  • Made with Unity
  • Learning
  • Support & Services
  • Community
    • Blog
    • Forums
    • Answers
    • Evangelists
    • User Groups
    • Beta Program
    • Advisory Panel

Unity account

You need a Unity Account to shop in the Online and Asset Stores, participate in the Unity Community and manage your license portfolio. Login Create account

Language

  • Chinese
  • Spanish
  • Japanese
  • Korean
  • Portuguese
  • Ask a question
  • Spaces
    • Default
    • Help Room
    • META
    • Moderators
    • Topics
    • Questions
    • Users
    • Badges
  • Home /
avatar image
0
Question by malkere · Dec 17, 2014 at 01:25 PM · inheritancerpginterfacevirtual functions

Trying to organize skill functions.

I'm still somewhat green on the subjects of polymorphism, interfaces, etc. What I'm trying to accomplish is an RPG skill system within a somewhat complex damage and statistics system in where different types of damage and resistances and things are being watched/calculated.

---Basically I'm trying to get a skill to perform a function.

As in the long run there will be hundreds of skills, passive, weapon, class, etc. I was going to put them into a SkillDatabase.cs as I've done with WeaponDatabase, etc. using:

public static Weapon shortSword = new Weapon(dmg, speed, etc);

however I was unable to figure a way to go that route if the Skill base class contains virtual functions, for example with:

public virtual void onUse ();

I can't then go:

public static Skill Strike = new Skill(onUse {yada yada}, etc); (right?)

So in looking for alternatives I started reading about interfaces and so changed Skill into ISkill with only { get; } for the values and gave up on the database idea, instead thinking of a script for each skill. The first test skill as follows:

 public class MeleeSkillStrike : ISkill {
     public string _name {
         get { return "Strike"; }
     }
     public Classes.currentClass _classRequired {
         get { return  Classes.currentClass.Squire; }
     }
     public int _levelRequired {
         get { return 1; }
     }
     public int _currentLevel {
         get { return _currentLevel; }
         set { _currentLevel = value; }
     }
     public skillCategory _category {
         get { return skillCategory.Class; }
     }
     public skillType _type {
         get { return skillType.Offense; }
     }
     public bool _passive {
         get { return false; }
     }
     
     public void OnEffect () {
         int newDmg;
         if (Mathf.RoundToInt(PlayerData.damage() * 1.1f) == PlayerData.damage()) newDmg = PlayerData.damage() + 1;
         else newDmg = Mathf.RoundToInt(PlayerData.damage() * 1.1f);
         PlayerData.player.GetComponent<PlayerScript>().target.GetComponent<MobAi>().TakeDamage(newDmg, PlayerData.damageType());
     }
     
     public void OffEffect () {
         //used for timed buffs, etc.
     }
 }

which is fine and works.... but at this point the only thing the interface is really doing is throwing errors for me if I leave any of the data out or input it incorrectly... not really what an interfaces main intention is I think, and really I might as well not implement at all and just hard code each skill if that's going to be the case...

can anyone think of a "why don't you just...." that I'm just not aware of?

To make things easier I suppose I can still make my database and just have it return the skill after hardcoding links into the database but... just seems like there should be an easier way to organize them I'm not getting... or is making a horde of scripts in neatly ordered folders totally acceptable?

thanks for any input.

Comment
Add comment
10 |3000 characters needed characters left characters exceeded
▼
  • Viewable by all users
  • Viewable by moderators
  • Viewable by moderators and the original poster
  • Advanced visibility
Viewable by all users

1 Reply

· Add your reply
  • Sort: 
avatar image
1
Best Answer

Answer by VesuvianPrime · Dec 17, 2014 at 01:38 PM

Interfaces are good because it means later you can write SomeFunction(ISkill skill) type logic that can accept any skill type.

You're probably going to see benefit in using an abstract base class at the same time, since you can provide default values there via virtuals.

I'm not sure what you're trying to do with the constructor. It looks to me like perhaps ISkill should have an event OnUseCallback that the parent subscribes to after instantiation.

Comment
Add comment · Show 6 · Share
10 |3000 characters needed characters left characters exceeded
▼
  • Viewable by all users
  • Viewable by moderators
  • Viewable by moderators and the original poster
  • Advanced visibility
Viewable by all users
avatar image malkere · Dec 17, 2014 at 01:59 PM 0
Share

ahhh, I see the benefit in being able to accept any skill type.

Currently I'm rena$$anonymous$$g: Weapon currentWeapon = (Weapon)WeaponDatabase.ShortSword to call currentWeapon.damage because it's inheriting the Item class, but is a Weapon not an Item..... I suppose that I wouldn't be able to SomeFuction(IItem item) if it was public static Weapon : IItem, IWeapon though would I? Or would I? It would have all the necessary IItem variables so I guess I could couldn't I.... hmmm I'll have to mull on that a bit.

As for my skill stuff basically I want to have lots of skills for example a Strength buff and a Strike attack, both of which are similar with 99% of their variables but the void OnUse() or whatever function needs to be defined differently for them all. Thus I couldn't get the simple hard-coded new Skill database approach to work because I can't add functions and their lines into the "public static Skill Strike = new Skill (yada yada)" approach.

So making a script for each skill will work fine, and with ISkill inheritance I can be sure that I can call them without error from other scripts... just seems like I'm missing some other way to handle varrying functions within a parent-child class relationship... maybe I don't fully understand virtual and override uses yet...

avatar image VesuvianPrime · Dec 17, 2014 at 03:57 PM 1
Share

Have moved from iPad to PC, so time for some examples. $$anonymous$$y approach would be something like:

 // ISkill is a convenient place to describe functionality for
 // skills and let the compiler tell you if anything is missing
 // in your implementation.
 public interface ISkill // : ICooldown, IEtc...
 {
     string name {get;}
     // classRequired {get;} - I just realized how awful calling an enum "class" is, try a different name!
     int levelRequired {get;}
     // etc
 
     void Use();
 }
 
 // AbstractSkill is where you can put default values and shared
 // functionality
 public abstract AbstractSkill : ISkill
 {
     // This is an example of providing a default value
     public virtual string name { get { return "Unnamed"; } }
 
     // This is an example of a property with no default
     // value and must be reimplemented in derived classes.
     public abstract int levelRequired {get;}
 
     // Sounds like Use needs to be reimplemented in every skill
     public abstract Use();
 }
 
 // Example of a concrete skill
 public ExplosionSkill : AbstractSkill
 {
     public override int levelRequired {get { return 1000000; } }
 
     public override Use()
     {
         Explode();
     }
 }

avatar image VesuvianPrime · Dec 17, 2014 at 04:04 PM 1
Share

Furthermore, I suspect you might like to replace your static hardcoded skill script with a factory

 public static SkillFactory
 {
     public static T GetSkill<T>()
         where T : AbstractSkill, new()
     {
         return new T();
     }
 }
 
 ExplosionSkill skill = SkillFactory.GetSkill<ExplosionSkill>();

Even better, we can add some caching:

 public static SkillFactory
 {
     private static readonly Dictionary<Type, AbstractSkill> s_CachedSkills;
 
     static SkillFactory()
     {
         s_CachedSkills = new Dictionary<Type, AbstractSkill>();
     }
 
     public static T GetSkill<T>()
         where T : AbstractSkill, new()
     {
         if (!s_CachedSkills.Contains$$anonymous$$ey(typeof(T)))
             s_CachedSkills[typeof(T)] = new T();
 
         return s_CachedSkills[typeof(T)];
     }
 }

avatar image malkere · Dec 18, 2014 at 01:07 AM 0
Share

I see I need to study examples of abstracts and overrides more thoroughly. That looks in fact like what I'm looking for. Thank you for the detailed response.

I'm not sure how the factory works, but I can look into that further now that I have the keyword and an example. Thank you.

avatar image malkere · Dec 18, 2014 at 02:24 PM 0
Share

I don't understand your SkillFactory you made for me... it doesn't let me play with it if I just copy and paste like that. Would you $$anonymous$$d explaining it a little more for me?

I tried reading documentation on factories but I can't get it to sink in XD

For now I've ended up hiding the inherited parent functions with "new public void OnUse()" and I can successfully hardcode them into a database script which calls fine and is returning the proper values. I still can't generate a List or any form of "ReturnAllSkills()" or "foreach (Skill in SkillDatabase)" for GUI program$$anonymous$$g, etc.

I think that's what you were trying to $$anonymous$$ch me with the factory but I don't understand it XD

Show more comments

Your answer

Hint: You can notify a user about this post by typing @username

Up to 2 attachments (including images) can be used with a maximum of 524.3 kB each and 1.0 MB total.

Follow this Question

Answers Answers and Comments

28 People are following this question.

avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image

Related Questions

Use of Interfaces To Handle Two Object Types 2 Answers

Can't Override Virtual Method In Inherited Class 1 Answer

Accessing interface in a derived class through the parent class 0 Answers

How to choose base class to make Inherit C# 2 Answers

Check if a trigger object implements an interface 2 Answers


Enterprise
Social Q&A

Social
Subscribe on YouTube social-youtube Follow on LinkedIn social-linkedin Follow on Twitter social-twitter Follow on Facebook social-facebook Follow on Instagram social-instagram

Footer

  • Purchase
    • Products
    • Subscription
    • Asset Store
    • Unity Gear
    • Resellers
  • Education
    • Students
    • Educators
    • Certification
    • Learn
    • Center of Excellence
  • Download
    • Unity
    • Beta Program
  • Unity Labs
    • Labs
    • Publications
  • Resources
    • Learn platform
    • Community
    • Documentation
    • Unity QA
    • FAQ
    • Services Status
    • Connect
  • About Unity
    • About Us
    • Blog
    • Events
    • Careers
    • Contact
    • Press
    • Partners
    • Affiliates
    • Security
Copyright © 2020 Unity Technologies
  • Legal
  • Privacy Policy
  • Cookies
  • Do Not Sell My Personal Information
  • Cookies Settings
"Unity", Unity logos, and other Unity trademarks are trademarks or registered trademarks of Unity Technologies or its affiliates in the U.S. and elsewhere (more info here). Other names or brands are trademarks of their respective owners.
  • Anonymous
  • Sign in
  • Create
  • Ask a question
  • Spaces
  • Default
  • Help Room
  • META
  • Moderators
  • Explore
  • Topics
  • Questions
  • Users
  • Badges