I want to make a selection script in unity 3d to select different types of objects
like units buildings or other stuff
i want to know how to change this type of line
if(hit.transform.CompareTag("Unit"))
{
SelectUnits(hit.transform);
}
else
{
DeselectUnits();
}
I want to use layers not tags for this and i don't know how to change this line
" if(hit.transform.CompareTag("Unit")) " into a line using layerMask not Tags in declarations.
Sorry for my bad english.
You don't want to use layer either for discriminate them. Use layer for it's purpose.
if you're dealing with components use Component.TryGetComponent. If not then just simply check is-a relationship between classes.
if(hit.transform.TryGetComponent(out AbstractUnit unit))
{
unit.SelectUnity();
}
else
{
DeselectUnits();
}
Related
I'm writing an RPG in C#, I have the character classes initialising nicely but I'm struggling with the attack classes.
Each attack will have its unique damage calculation formulas based off of multiple stats and eventually decorators.
Is there a way to dynamically create/append these damage formulas and decorators, or should I create a unique class for each attack that extends a generic attack class?
Here is some Pseudocode for what I'm after:
public class Attack
{
public string Name {get; set;}
List<Decorators> DamageCalc;
public Attack(string[] data, List<Decorators> decorators)
{
Name = data[DataList.Name]; //I'm using constants to keep my indexes readable
DamageCalc = data[DataList.Damage]; //i.e. strength * 10 + agility
Decorators = decorators
ApplyDecorators(Decorators)
}
public double DamageCalculation(Character attacker)
{
return DamageCalc; //attacker.Strength * 10 + attacker.Agility
}
...
}
Flexibility to add new features and behaviours is of particular interest to me.
Many thanks for your input!
Edit 1
Where I to use JSON, would there be any simple way to relate JSON fields to my Character class's stat variables or do I need write custom code to interoperate it?
Off hand I can't think of a tidy way to use a JSON field, or any field for that matter, that can dynamically collect information from my Character class.
Edit 2
Ideally this would allow me to dynamically create all my attacks as instances of a single attack class by taking data from a JSON file, string, XML file or database table.
I changed the code sample on the DamageCalculation method.
Closed
I the selected answer does provide a solution for my particular problem. It seems that I really would have to write code to parse formulas and generate the dynamic tool that I'm envisioning. As such I will see if I can get around this particular problem from a design perspective.
You need to write a base class that contain the signature of your calculations and on the derived classes implement them based on their specialty.
It is a solid, and you can find more about it under the title of "Strategy Design Pattern"
In an example game engine server, the game world could be represented by a World object. The game might have multiple game worlds and a player who is in a world only needs to receive position data of units in that world.
class World
{
public List<Unit> Units { get; set; }
}
However a piece of code also needs to be able to look up what world a unit is in easily, so the unit object itself keeps track of a world reference.
class Unit
{
public World World { get; set; }
}
This works for lookup, but quickly becomes problematic when changing data when the programmer isn't aware of the relationship between objects going on, so I changed Units in World to be readonly and have the following code in Unit.
public virtual World World
{
get { return _world; }
set
{
// Unit must always be in a world
Contract.Requires<ArgumentNullException>(value != null);
// If already this, don't do anything
if (value == _world) return;
var oldWorld = _world;
_world = value;
if(oldWorld != null) oldWorld.UpdateUnitEntry(this);
_world.UpdateUnitEntry(this);
}
}
This works, but it feels like there's a better way to do this. Especially as I add more stuff that needs to be linked the same way (a World also has Structures and Players), a lot of repeated functionality comes in. Is there a better way to achieve this one-to-many relationship without manually updating both sides?
In languages like C++ which don't have such sophistaced reference management and GC, having cyclic references like this a problem anyway(e.g. SharedPtr).
This also problem for e.g. serialization of the game state.
This leads me to believe that there might be a better way to approach that issue general.
E.g. Do the Units really need to know their World?
Maybe look at that code that made you think you'll need that and maybe you can change it in way that this won't be required anymore.
So, maybe implement an entity management system and only referencs your game entities by an abstract ID or handle. Resolve the ID/handle before acting no the object behind but do not have an entity keep store a reference to another entity.
If you find yourself wanting to serialize the game's state this will also help greatly.
Otherwise:
What you are doing is not strictly wrong or anything. If it is working and not too much of a pain, just keep it like that.
I'm playing around with writing an item crafting system that I might want to put into a game someday. There are Recipes which specify the ingredients they require and what they produce.
I wanted the recipes to be flexible, such that they only required a broad category of ingredients, not an exact one. For example, a recipe for a weapon blade might just say it requires a metal, not specifically steel. The recipes have to verify that the ingredients given are within the acceptable category. Some materials might belong to multiple categories.
Then I had a possibly brilliant, possibly insane idea. The .net type system already implements that! So for each material, I add a property of type Type, and use IsAssignableFrom to verify the ingredients' compatibility.
I have a file that looks like this:
public interface ItemType { }
public interface Material : ItemType { }
public interface Metal : Material { }
public interface Gold : Metal { }
public interface Silver : Metal { }
public interface Iron : Metal { }
public interface Steel : Metal { }
public interface Wood : Material { }
public interface Coal : Material { }
And so on. None of those are ever implemented. I'm just borrowing the built in type checking for my own purposes.
Is there anything necessarily wrong with this?
edit: actual question
If I've been clear enough to explain what I'm trying to accomplish here, then what would you suggest is a good way to go about it, ignoring this whole type system abuse thing? Would you have also used this solution, or something else?
Second question, are there any pitfalls to watch out for in what I've done here?
Is there anything necessarily wrong with this?
Yes, everything.
Classes and interfaces are meant to express behavior. There is no behavior in your code. Your code is not miscomunicating the intentions. Usually, when you see interface, you expect it to have some method and that method is called. That is not the case here.
It will become impossible to define the materials and recipes in some kind of configuration/resource file, like most normal games do. So you have to recompile every time you want to change the materials or recipe a little.
It will become problematic to create items/materials that are somehow related. For example, lets say there are multiple tools and each tool can be from different materials. In your case, you have to write down every combination. In ideal case, you can just run few nested for loops which create each combination.
You cannot parametrize the materials in any way without creating classes of them. For example, you might want different colors of wool. How would you do it? Create interface for each color? Or use some kind of enum as parameter. But you have to create class for that.
Better way would be simple Item class that has collection of tags. Even simple strings should be enough.
I have been looking around how to make one array with many different enums.
What I am trying to do is have enums with for example
public enum playerTeam
{
Red,
Blue
};
and another with
public enum currentWeapon
{
Knife,
Gun,
Rifle,
Shotgun,
SniperRifle,
RocketLauncher,
Grenade,
Molotov,
FlameThrower,
ProximityMine,
RemoteMine
};
and then assign them to a array called something like
Players[]
Then being able to loop trough the array and set values of each enum. I have used the enums without array before. To set/get data of the player.
But now I am about to expand my project to multiplayer. And I cant figure out how to add enums to one array. As that would make code a bit easier to handle.
This was really hard to explain, hope you guys understand..
I'd suggest you create a class Player which has members Weapon and Team. Then use player instances to perform operations.
class Player
{
Weapon CurrentWeapon {get; set;}
Team Team {get; set;}
}
That's a weird way to look at things, considering what C# allows you to do. At best, to achieve exactly what you want, you could use something that maps keys to values (players to weapons/teams), like the System.Collections.Generic.Dictionary.
But there's really no need to do that. The Player class should contain that info in two fields:
class Player
{
...
private Team currentTeam;
private Weapon currentWeapon;
...
}
Judging by how you named your enums, and by your idea, I'm thinking you should also follow a learning resource for C# and OOP, from beginning to end.
This is a bit ridiculous because team is definably not a weapon (wtf is it currentWeapon. and not Weapon) but if you're asking how to use an enum and bit flags you could write
[Flags]
public enum Weapon
{
...
WeaponMask = 0xFF
IsBlueTeam = 0x0100
}
Which allows you to do
switch(player[i] & WeaponMask) { case SomeWeapon: ... }
isBlueTeam = (player[i] & IsBlueTeam) != 0 //assuming its either blue or read
I need to display some stats, numbers, and graphs about various game objects on the screen.
(examples: camera position, field of view, frames per second, fill rate, number of objects culled, etc... )
Currently any object which wants to be graphed or displayed implements an interface along these lines:
public interface IGraphable
{
float GraphableValue { get; set; }
}
Then that object can be sent to a graph component to be displayed. This has some obvious drawbacks like not being able to graph 2 different pieces of data which belong to the same class.
What I want is a way to pass a pointer to where the data is located or a pointer to a function which knows how to return the data instead of passing the object to the display component.
I believe that this is what delegates are for but I don't understand how to use them in this context (Actually I don't understand them very well at all). Also, is there another (smarter/better) way to do this?
Thanks!
Why not invert the control like this:
public interface IGraphable
{
void BuildGraphable( IGraph g );
}
interface IGraph {
void AddValue( double value );
}
this is a preferred option in OO anyway as it hides details of the IGraphable implementation. Additionally you can now extend IGraph for added functionality without breaking compatibility.
Depending on how you're doing things, you could possibly use Reflection (attributes on accessors), although that can be relatively confusing at first too. But it's a very useful tool in your arsenal, so it's well worth spending the time on. Here is a great tutorial on how to use them:
http://www.brainbell.com/tutors/C_Sharp/Attributes.htm
But then, learning delegates is also very useful, and that does sound like a good solution. I haven't looked deeply into it, but this tutorial on the same site might be useful:
http://www.brainbell.com/tutors/C_Sharp/Delegates_and_Event_Handlers.htm
I have decided to do the following:
public class GraphComponent
{
private Func<flaot> _function;
public GraphComponent(Func<flaot> function, ...)
{ ... }
}
This allows me to specify how the data is retrieved by writing something like this:
FPSComponent fpsc = new FPSComponent();
GraphComponent fpsg = new GraphComponent(delegate() { return fpsc.ApproximateFPS; }, ...);
What I want is a way to pass a pointer to where the data is located or a pointer to a function which knows how to return the data instead of passing the object to the display component.
If you don't want to add your objects to your graph component BECAUSE
This has some obvious drawbacks like not being able to graph 2 different pieces of data which belong to the same class.
Maybe a list will solve your problem ?
public interface IGraphable
{
List<float> GraphableValues { get; }
}