Sign in to follow this  
rogerdv

Unity RPG item/spell/combat system

Recommended Posts

Im working in the implementation of the combat system for my RPG (made with Unity3d and c#), which depends on the item system, skill system, etc. The idea is to have real time pausable combat, so my initial idea was to have a queue of actions. An action can be a weapon attack or an spell, and can be created by the AI or the player input during combat. But when started to work on the actual implementaiton I thought that perhaps my system was too complex.

Described in pseudocode, it something like this:

 

On the Update() of each entity (including player)

if queue is not empty

 get the first action if cooldown timer expired and it is loopable, else, remove and get next

 is it an item action?

    if the item is a weapon then get the item dmg properties, the target protect properties and decide if it is a succesful attack, dmg, etc

    if the item is something else, decide what to do

 is it a spell cast?

     then do the spell stuff, etc

 set the cooldown timer

 

The advantage I see: the item class is generic and can contain any item, because it just hold properties, doesnt knows how to actually use the item.

The disadvantage: the same. Also, the gameplay code becomes complex (you have to compare all the item damage types against all the target protection types). The action class is a mess: it must contain all possible combinations of actions: item on actor (like a sword attack), spell on actor, and any other I can figure out later.

Is there any other more optimal solution to this?

Share this post


Link to post
Share on other sites

I'm the author of a real-time pausable RPG. To answer your basic question, "Do I have to do all that stuff?" Yes, you do. In fact, I think you simplified; for an attack, my code runs three timers. One for a character preparing to attack, but not yet attacking, who should display a fighting animation. Second, when the character actually is attacking, to display the attacking animation. And third, when the character is recovering from his attack, displaying a recover animation (i.e. moving his sword back from the extended position to the ready position). Real-time is complicated!

 

Now, how to handle it in code? For your action class, I have a similar set of classes. However, I subclass depending on the particular action. So "attack with a weapon" in one subclass, "cast a spell" is another, etc. Is something like that possible in your architecture? If so, you should be able to avoid having one mega-action class. I actually have one giant class that handles running all the actions through a switch statement. I'm not proud of this architecture, but there are not that many types of actions, so I live with it, and it works fine. You can probably do better than that, though, if you are writing code from scratch, by moving some or all of the action-running code into the sub-classes.

 

Hope that helps a little,

Geoff

Share this post


Link to post
Share on other sites

Well, you say you have a base class, for example "Attack" and that spells, sword swipes etc Derive from it?

 

The details of how to use the item should be handled by the derived class. The caller should not be concerned with this and should just call some "activate()" or "use()" method.

 

You could also have a factory system, whereby the sword generates attack derived objects and the spellbook (or whatever is source of your magic) does the same. These can be created dynamically based on the attack type. 

 

If you can't make it work like that currently and the caller directly reads properties from the class and internally performs the action this is what is causing the confusion, refactor it to black box the use/cooldown code.

 

Hope this helps!

Edited by braindigitalis

Share this post


Link to post
Share on other sites

Well, you say you have a base class, for example "Attack" and that spells, sword swipes etc Derive from it?

 

The details of how to use the item should be handled by the derived class. The caller should not be concerned with this and should just call some "activate()" or "use()" method.

 

You could also have a factory system, whereby the sword generates attack derived objects and the spellbook (or whatever is source of your magic) does the same. These can be created dynamically based on the attack type. 

 

If you can't make it work like that currently and the caller directly reads properties from the class and internally performs the action this is what is causing the confusion, refactor it to black box the use/cooldown code.

 

Hope this helps!

 

Nope, I dont have a class Attack. What I do plan to have (not yet) are classess for abilities you can apply on targets. I will follow your advice and derive specialized item classes, that will help to clear my game logic code.

Share this post


Link to post
Share on other sites

You might look into creating an interface for your attack items and implement this in your derived classes.  This would then allow separation of the data structures and game logic of how they work but still allow you to store them in a simple data structure.

 

For example if we have an interface defined like:

interface iAttackable
{
    void Attack();
}

Then we could define a sword and spell class like this:

public class Sword : iAttackable
{
    public void Attack()
    {
        //...Do some logic in the attack
    }
}

public class Spell : iAttackable
{
    public void Attack()
    {
        //...Do some logic in the attack
    }
}

This way now you don't have to do a check on an object to see how to perform a specific attack.  Abstracting it this way now allows for different logic to be handled by the unique class.  You may need to add parameters to the interface in order to share objects between class but this information would be something you will need to figure out in your design.  Now then back to the interface and now that we have defined the usage in two classes we could write code like:

//....Update method definition skipped
iAttackable attackItem = new Sword(); // Or this could very well be "new Spell();"
attackItem.Attack();

Because the attackItem is a generic interface class we can store either the Spell class or the Sword class in this variable.  With this you can now even stack different kind of attacks so if a player wanted to use a sword and a spell they could without bloating your code just create a data structure to manage it.  Having a generic enough way to access different types of classes can be beneficial in a complex system.  One class can also implement multiple interfaces which then can allow you to blend different features generically into one class.  For example you may need to do something special on the spell being cast during the update process.  You can use type casting to these specific interfaces and then test if the cast worked before your proceed.

 

This is just one different approach that could help solve your design problem.  Try a couple of different ideas and see how it works best for your design.

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this  

  • Forum Statistics

    • Total Topics
      628278
    • Total Posts
      2981789
  • Similar Content

    • By ForgedInteractive


      Who We Are
      We are Forged Interactive, a small team of like-minded game developers with the sole purpose of making games we love! We're a team of artists, animators, programmers, level designers, writers, composers, producers, and other creative minds. We want to make games that you, the modern gamer want to play! We hope to build a community that enjoys our games as much as we love creating them. With your feedback and support we will be able to achieve that.

      About the Game
      GAME NAME is a fun, action-packed army builder with unique characters, challenges and engaging levels. Set forth on an adventure to protect friends, family and countrymen from new adversaries. Once defeated your enemies turn coat and join you in your adventures. Players can enjoy a range of troops and abilities based on their gameplay style which become more important as maps introduce more challenging terrain, enemies and bosses. Strong orc knights, dangerous shamans, and even a dragon are out on the prowl. Knowing when to fight and when to run, and how to manage your army is essential. Your actions alone decide the fate of this world.

      Previous Work by Team
      Although we are working towards our first game as a team, our team members themselves have past experience in the industry.
      This includes members who have worked on titles including:
      Final Fantasy Kingsglaive, FIFA, Xcom 2 and Civilization.

      Who are we looking for? 3D Modellers Concept Artists Marketing Specialists Level Designer

      What do we expect? Reference work or portfolio. Examples what have you already done and what projects you have worked on academic or otherwise. The ability to commit to the project on a regular basis. If you are going on a two-week trip, we don't mind, but it would be good if you could commit 10+ hours to the project each week. Willingness to work with a royalty based compensation model, you will be paid when the game launches. Openness to learning new tools and techniques
      What can we offer? Continuous support and availability from our side. You have the ability to give design input, and creative say in the development of the game. Shown in credits on websites, in-game and more. Insight and contacts from within the Industry.
      Contact
      If you are interested in knowing more or joining. Please email or PM us on Skype. Myself or Colin will reply to you within 48 hours.

      E-mail: Recruitment@ForgedInteractive.com
      Skype: ForgedInteractive

      Regards,
      David and Colin

      Follow us on:

      Facebook: https://www.facebook.com/ForgedInteractive/
      Twitter: @ForgedInteract
      Youtube: https://www.youtube.com/channel/UCpK..._as=subscriber
      Reddit: https://www.reddit.com/user/Forged_Interactive/
    • By Eck
      I just saw their courses were knocked down to $10 each and figured I'd share the info here. They have stuff for Unity, Unreal, drawing, business, etc. I haven't used their stuff before, but the previews I looked at seemed pretty good and there is a user review system as well.
      https://www.udemy.com/courses/search/?q=Unity&src=ukw
      - Eck
       
    • By zizulot
      first and only logo , for now
    • By sidbhati32
      I am working on a game in which we control a rectangular box at the bottom of the screen. Three sphere which has alphabets in it fall down. When the game starts, a word is generated from the predefined list of words(which I'll give) and we are supposed to touch the correct sphere having the alphabet based on that word. The question is how to detect if I have touched the correct sphere. 
      secondly, if I have touched a correct sphere before and there is no recurrence of that alphabet in that word then during the second wave the game should not proceed if I touch the same alphabet again.
      Looking forward to your answers, i have to submit this project in a couple of days. please help! (Working on Unity 3D)
      Thanks
    • By NDraskovic
      Hey guys,   As the title says, I'm trying to control a desktop game by using my mobile phone as a controller.  I created two scenes, one that acts as a server, other as a client.    Server has this code: void Start () {         Test = "Nothing yet happened";         NetworkServer.Listen(25000);         NetworkServer.RegisterHandler(888, ServerReceiveMessage);     }         private void ServerReceiveMessage(NetworkMessage message)     {                 StringMessage msg = new StringMessage();         msg.value = message.ReadMessage<StringMessage>().value;         if (!String.IsNullOrEmpty(msg.value))         {             Test = "Message received";             string[] deltas = msg.value.Split('|');             Horizontal = Convert.ToSingle(deltas[0]);             Vertical = Convert.ToSingle(deltas[1]);             TestScript.MoveForward(Vertical);             TestScript.RotateAroundY(Horizontal);         }         else         {             Test = "Nothing received";         }     }  
        And client this:  private void Connect()     {              client.Connect(IPAddress, 25000);           }     void Start () {         client = new NetworkClient();         Connect();            }         void Update () {    #if UNITY_ANDROID         MobileTouches = Input.touches;         if (MobileTouches.Length > 0)         {             for (int i = 0; i < MobileTouches.Length; i++)             {                 if (MobileTouches[i].phase == TouchPhase.Moved)                 {                     Horizontal = MobileTouches[i].deltaPosition.x;                     Vertical = MobileTouches[i].deltaPosition.y;                 }else if(MobileTouches[i].phase == TouchPhase.Stationary)                 {                     Connect();                                  }             }         } #elif UNITY_EDITOR               Horizontal = Input.GetAxis("Horizontal");         Vertical = Input.GetAxis("Vertical"); #endif         thumb.Translate(Vector3.up * Vertical * Time.deltaTime);         thumb.Translate(Vector3.right * Horizontal * Time.deltaTime);         SendControllerInfo();     }     static public void SendControllerInfo()     {         if (client.isConnected)         {             StringMessage msg = new StringMessage();             msg.value = Horizontal + "|" + Vertical;             client.Send(888, msg);         }     }  
        Ip address is hard coded, I just replaced it with the "IpAddress" variable. The code itself builds fine, and when I try to run in on a desktop computer, it works as expected (just a simple movement of an object on the server screen). However when I try to publish the client scene to a mobile device (Android), it doesn't connect to the server. They are both connected to the same network. Can anyone tell me what the problem might be?   Thanks
  • Popular Now