In order for a class to be attached to a GameObject it needs to inherit from MonoBehaviour. If I create a base character class that contains all the attributes shared by both NPCs and PCs, how do I create instances of that class and attach it to game objects? To give a concrete example of the problem, if the base character class has variables like health, stamina, strength etc, and I want a particular game object to have a particular set of those attributes, how do I attach that to a game object as it cannot inherit the base character class?
I suspect the mistake I'm making is to think that these instances need to even be attached to the objects that I want them to be associated with, but some clear guidance here would be most appreciated.
It seems that what you really want is a base class that also allows its children to be MonoBehaviours. You can accomplish this by making your base class an abstract MonoBehaviour and inheriting from it.
public abstract class Base : MonoBehaviour
{
protected int HP;
}
Then your children of this class will also be MonoBehaviours which you can attach to GameObjects.
public class Ninja : Base
{
void Start()
{
HP = 100;
}
}
Related
I have a class Monster
class Monster
{
move()
attack()
}
using inheritance we could create:
melee monster : monster
overr attack()
ranged monster : monster
ovverr attack()
flying monster : monster
overr move()
swimming monster : monster
overr move()
How to create FlyingRangeMonster and MeleeSwimmingMonster without duplicating code?
I suppose we should abandon inheritance and use composition. How to realizate it in this case ?
Thank you!
You should create some methods to evaluate move or attack. If you need new monster class with the same move ability, you just override move or attack to those methods.
So for every type of monster you have one class and overridden methods, I don't see this as duplicated code.
What you are probably intending is inherit class from two classes, but it is not allowed in C# (I think it is possible in C++).
What I would do is create two interfaces, one for moving monsters and one for attacking monsters. You still need implement methods in you monster classes, but you can combine them as you wish. Also you can easily identify if your monster implements moving or attacking interface (or both) - if (myMonster is IMovingMonster) ....
You also can inherit from class and interface, so MeleeSwimmingMonster can by inherited from MeleeMonster and moving interface (or SwimmingMonster and attacking interface). For public class MeleeSwimmingMonster : MeleeMonster, IMovingMonster there you don't need to override attack() method, if it is same as in MeleeMonster class.
And if you want new ability (singing), you just create new singing interface and you can create new type of singing monsters. So your public class MeleeSwimmingSingingMonster : MeleeSwimmingMonster, ISingingMonster can do same moves and attacks as MeleeSwimmingMonster, but you can learn it some song!
I am attempting to create a 2D game in Unity. Essentially, there are multiple types of 'agents': enemies and players. Programmatically, both classes 'enemy' and 'player' derive from the agent class. Then, there are different types of enemies (such as flying, ground enemies, etc).
My issue is that I need to call the Update function on all derivatives of an enemy. This is because there is code that needs to run for all enemies, and other code that should only run for some enemies - all enemies need to know where the player is, but only some enemies need to fly.
I read somewhere that you can use the new keyword, then call the base update function. However, with multiple levels of subclasses this seems inefficient and clunky as you have to state "new" for each new instance.
Is there any better way to call Update, Start and FixedUpdate (functions that are automatically called) than how I have implemented this below? Thanks in advance.
public abstract class Agent : MonoBehaviour
{
public void Start(){
// Run start code for all types of 'players', including AI
}
}
public class Enemy : Agent
{
public new void Start()
{
base.Start();
// Run start code specific to all enemies
}
}
public class WalkerEnemy : Enemy
{
public new void Start()
{
base.Start();
// Run start code specific to walking enemies ONLY
// Invoking Enemy.Start() will result in a call of Agent.Start() as well
}
}
Thank You for your help. Whilst I would call myself 'intermediate' in my programming skills, I doubt my object oriented knowledge is as fluent as it could be. So if there is some fundamental idea that I am missing, please let me know :)
First of all, when using inheritance structure, you usually want to avoid using the new keyword. Instead you mark the methods of the base class which you want to change for inheriting classes with the virtual keyword (or abstract if the baseclass does not contain code). That way you can re-use the code in the baseclass or even remove it all together.
An approach which may be even better in your case is to make an abstract method which you call in your baseclass start method. That way, inheriting classes MUST implement the method. This will be forced by the compiler.
Example:
public abstract class Agent : MonoBehaviour
{
private void Start(){
// Your code needed for all inheriting classes here.
// Call the abstract method which is defined on inheriting classes
OnStarting();
}
protected abstract void OnStarting();
}
public class Enemy : Agent
{
protected override OnStarting()
{
// Your enemy code here.
}
}
public class WalkerEnemy : Enemy
{
protected override OnStarting()
{
base.OnStarting(); // Call the code from the Enemy class
// Your walker enemy code here.
}
}
Also as you might see, I made your Start method private. Since Unity calls this by itself. You do not want to call this yourself from anywhere in your application. The OnStarting methods are marked as protected, because they should only exist/ be used in the scope of this inheritance tree.
I'm writing a game and would like an opinion on my class hierarchy.
Currently I have an Character class, an AICharacter class and a KnightCharacter class.
Character holds things like Death() which all characters must facilitate, AICharacter overrides Death() with extra details for AI driven characters. KnightCharacter overrides Character stuff like handling of Shields(Only for Knights).
How can I elegantly allow my player to possess a KnightCharacter : Character and my AI to posses a KnightCharacter : AICharacter : Character?
I bascically want to only implement the AICharacter when its being controlled by an AI.
Thanks
One approach that gives a lot of flexibility is to break your characters and objects down into various aspects, where each aspect is its own class. Some examples of aspects that an action or RPG character might have are Health, Mana, WearsEquipment, UsesItems, MobileObject, PhysicalRigidbody, MeleeAttackPerformer, RangedAttackPerformer, MagicAttackPerformer, PlayerControlledMobile, AIControlledMobile, and even things like AudioSource, etc, etc... Each of these classes would derive from a common base, e.g. AspectMixin or something like that.
If you treat each of these classes as Mix-ins, then you gain a lot of flexibility in creating new archetypes that have the aspects that make sense for that type of actor. This will allow, for example, monsters and players to share the fact that they have health, but have different classes for controlling them (AI-controls vs player-controls). Further, the Health aspect can be added to a stationary object (e.g. a barrel), to allow it to be affected by damage.
To achieve this, your archetype objects store a list of aspects mixins for that archetype. Further, the aspects need to be able to query the main object for other aspects by type (or interface). It's a bit of work to set up, but that's the price of flexibility.
FWIW, this is the approach that the Unity Engine tries to encourage (consider they call them MonoBehavior: behavior..aspect...different words for the same concept), though many developers don't "get it" until they've made several failed prototypes in which classes quickly become monolithic.
To go back to your original question, it sort of depends on how many playable classes you have, and whether AI can control characters of the same classes. If so, it would best to abstract the Controls out of the characters, then have AIControls and PlayerControls derive from Controls, either of which is able to interface with your character class.
On the other hand if AI types can be broken into just a few various behaviors (aggressive monsters, peaceful NPCs), I would make each one an aspect.
What you're asking isn't possible with ordinary c# inheritance. Your brother can't have a different grandfather from you.
Since you seem to be looking for ideas, here's one that uses generics:
abstract class BaseController
{
virtual GameEvent ReadNextEvent();
}
class PlayerController : BaseController
{
override GameEvent ReadNextEvent
{
return userInterface.ReadNextEvent();
}
}
class NonPlayerController : BaseController
{
override GameEvent ReadNextEvent
{
artificialIntelligenceEngine.Think();
return artificialIntelligenceEngine.ReadNextEvent();
}
}
abstract class Character<T> where T : BaseController
{
protected T controller;
abstract ProcessEvents();
}
class KnightCharacter<T> : Character<T>
{
override ProcessEvents()
{
var e = controller.ReadNextEvent();
switch (e.Action)
{
1 : SwingSword(); break;
2 : LiftShield(); break;
3 : Yell("None shall pass!"); break;
}
}
}
class Program
{
void Example()
{
var playerKnight = new KnightCharacter<PlayerController>();
var aiKnight = new KnightCharacter<NonPlayerController>();
}
}
I am designing a card game in C#. Each card is an instance of the Card class that contains two properties: a unique ID for the card and a reference to a CardData object. The object of type CardData implements the methods regarding how the Card functions within the game rules. Many cards (ex. if there are multiple jack of clubs) can reference the same card data.
public class Card {
public int id;
public CardData card;
}
My question is regarding how I should implement the CardData class. My first instinct was to design an abstract base class CardData with a bunch of methods like WhenPlayed() and WhenRemoved(), and then have a subclass for each card that implements them.
public abstract class CardData () {
public abstract void WhenPlayed();
public abstract void WhenRemoved();
}
public class JackOfClubs : CardData () {
public override void WhenPlayed() {
Console.WriteLine( "You played a Jack of Clubs!" );
}
public override void WhenRemoved() {
Console.WriteLine( "Bye for now" );
}
}
However, since I never want to actually instantiate a JackOfClubs object, but rather instantiate Cards and give them a reference to the JackOfClubs class, it would make sense to make the CardData class and all subclasses static. This creates a problem, because as far as I know static classes cannot inherit.
Furthermore, I considered using an interface but I wanted the possibility of default methods. For instance, if 90% of my CardData objects implement WhenRemoved() as "Bye for now", it would be tiresome to retype that for each subclass. I could use a non abstract CardData class to achieve this, but not an interface.
My question is what would be the best or correct approach to handling a class structure such as this, if there is one.
I would do a design like thisplease refer the diagram, so that you don't create as many classes as there are many cards, essentially they are different objects of the same class. So we have factory that holds a custom collection called Cards which is a collection of Card class that has a type and value. You can implement the play method depending on the type and value o the card. In the case that you are playing a game where all the cards are not involved, this design just works fine, in the case that you are extending this to multiple card games, if you add one more class card category, this design encompasses that as well. Hope this helps.
I have two classes in XNA.
maingame.cs
and
player.cs
In my maingame.cs I have a rectangle that is drawn wherever the mouse is, I use this for clicking.
My player.cs has a rectangle for the players sprite.
I Have No idea how to make these two classes 'talk' to eachother so that I can have something like
if (ButtonState.Pressed == mouseState.LeftButton && mouseRectangle.Intersects(playerRectangle))
{
//draw something
}
The problem is that playerRectangle is in the Player.CS and the mouseRectangle is in the maingame.CS
How do I get these two to talk to eachother? I've been Googling for hours now with no luck.
Player.CS looks like
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework;
namespace PlanetDefence
{
class Battleship
{
//Textures
Texture2D playerBattleshipTexture;
//Rectangles
Rectangle playerBattleshipRectangle;
//Integers
public Battleship(Texture2D newPlayerBattleshipTexture, Rectangle newPlayerBattleshipRectangle)
{
playerBattleshipTexture = newPlayerBattleshipTexture;
playerBattleshipRectangle = newPlayerBattleshipRectangle;
newPlayerBattleshipRectangle = new Rectangle(100, 100, 100, 100);
}
public void Update()
{
}
public void Draw(SpriteBatch spriteBatch)
{
//Draw the player Battleship
spriteBatch.Draw(playerBattleshipTexture, playerBattleshipRectangle, Color.White);
}
}
}
I'm trying to make it so that my mouse rectangle in MainGame.CS is able to click it by doing
if (ButtonState.Pressed == mouseState.LeftButton && mouseRectangle.Intersects(playerBattleshipRectangle))
{
playerBattleship.Draw(spriteBatch);
}
I'm not sure if I'm stating the obvious here, but you need a public accessor for your Rectangle in your Battleship class. If you don't understand what that means then you need to do some reading on the basics of object-oriented programming. For now, though, if you modify the code of your Battleship class to say
public Rectangle playerBattleshipRectangle;
... you can then access it from your maingame.cs' reference to the player object using
player.playerBattleshipRectangle
(assuming your player is a Battleship class. If it's not then you need to be more clear in your question and post the class source code for whatever class your player is. You say "player.cs" but post the class Battleship-- which is it? If the filename is player.cs but the class name is actually battleship you should change one of them so that they are the same. Practice good, easy to understand class and variable names; be as descriptive as possible without being too wordy).
By default, if you include no scope modifier (public, private, protected, internal...) before your member fields in a class, then they are set to private and not accessible by other classes.
You can also use Properties to have more control over access to a class' member fields. For instance,
private int health;
public int Health
{
get { return health; }
set { health = MathHelper.Clamp(health, 0, 100); }
}
this code contains a private (only this class can access it) definition of the health of an object. It also provides a public way for other classes to 'see' the health of that object and change this health. As you can see in the 'set' section, when another class sets the health of this object it is automatically clamped between 0 and 100. You could also omit 'set' entirely and no other class could change the health, they could only see it.
This is all the basics of object-oriented programming in C#. I strongly encourage you to start from the basics if you don't know them. You cannot successfully create a game without understanding scope, properties, inheritance, object instances and references, just to name a few.
A quick summary of some relevant definitions from this post:
field - aka a variable; a basic trait stored in a class as a 'member'. i.e., 'health' or 'boundingBox'.
property - an accessor for a field which is useful for defining how outside classes can see and modify it.
instance - a 'real' object which is stored in memory. a class only defines the behavior of an object; it must be made into an instance for the object to actually exist. A class like Battleship can be used to make unlimited instances of battleships in memory. When you say Battleship player = new Battleship(), you are creating an instance of Battleship called 'player'.
private - placing 'private' before a field means only this class can see it.
public - placing 'public' before a field means all classes can see it.
protected - placing 'protected' before a field means only this class and any classes inherited off of this class can see it.
internal - placing 'internal' before a field means only classes in this class' namespace can see it.
I apologize if I underestimate your knowledge of the subject.
One of the classes needs to hold a reference to the other.
With such a reference, it can call methods on it, set properties etc.
You can do this by passing in an instance in the constructor or as a property.
public Maingame(Player player)
{
// use the Player instance
}
To access it outside of the constructor, you should use a field and assign it in the constructor (or property setter, whichever you decide to use):
Player myPlayer;
public Maingame(Player player)
{
myPlayer = player;
// use the myPlayer field in the class
}
To avoid tight coupling, you may want to investigate using events.