public class Node : IHeapItem<Node> {
//IHeapItem is for a heap i use for pathfinding
public int x;
public int y;
public ??? reference;
// constructor
public Node(int a, int b , ??? r){
x = a;
y = b;
reference = r;
}
// other unrelated stuff
}
What data type should reference be? I am confused how i can make it flexible to accept different types.
The trick is not to have a datatype that changes (which is impossible in a strongly-typed language like c#) but to use a base type of all the classes that could be referenced here. If you create a new Actor script which is inherited by NPCActor and PlayerActor, all three classes can be equated with your reference field.
If any class in existence should be put there, simply take object as declaring type. Every type in .NET languages inherits from this class and can therefore be but there.
use a interface, that all things you want to reference implement, and get it by the interface, or give them all a common parent class and get it by the parent class.
If you are just interacting with a certain few methods of properties of each one a interface is perfect, or you could use a abstract base class as well.
Figure out what relates all the different types that could be referenced there.
They all are scene objects like GameObject, Transform, some custom Component, Collider, etc… then use the related type for that UnityEngine.Object (they all inherit from that). This one is also useful for if it needs to be serializable by reference by the unity serialization system, and can drag and drop in the inspector. Note you can do sub types of this as well… like 'they’re all custom scripts that inherit from MonoBehaviour… or Component… then use MonoBehaviour or Component.
They all are custom types you defined that have some related function like ‘Foo’… then they all should implement some interface ‘IFooable’ and then the field/var could be that type.
They can be ANYTHING under the sun, from an int, to a GameObject, to some custom type… use System.Object, which ALL types inherit from, no matter what (note placing struct/prim types like int into a object field causes boxing and takes up space on the heap and incurs GC).
The list of Nodes always contains nodes that reference the same type, but you may have different lists of Nodes that reference other types. Like a List of Nodes that reference Transforms, and a List of Nodes that reference IFooables. In this case use what @Kiwasi suggested with generics.
In the end… it depends on what sort of restriction/freedom you expect from Node.
If you want end all be all freedom where it does NOT matter… use System.object. But it’ll be slow and you’ll be constantly checking ‘if reference is thisType’ or ‘if reference is that type’…
Where as if they’re all Components, you can treat them as Components. Because the reference is that type. You know they have a ‘transform’ property and a ‘gameObject’ property.
What do you mean by does the type change? Do you mean, do i change the reference at a later date to a difference class for a specific node? If so, then no, once the node is set with the reference - that reference will remain that way. So does that mean i can use T?
You mean write an ‘interface’… and how do you not know how to write an interface, you have one called ‘IHeapItem’ above… I assume you know how to implement generics and interfaces from that… if you don’t, then who wrote ‘IHeapItem’???
Also, only use an interface if the types you want to reference are types you can actually modify the code for. If you plan to reference things like Transform, or GameObject, an interface will be of no use to you.
public class Node <T> {
public int x;
public int y;
public T reference;
// constructor
public Node<T>(int a, int b , T r){
x = a;
y = b;
reference = r;
}
}
Not sure how well this will interact with your interface, might need to make that generic as well.
The idea I have here is, each node is located in rooms. And if a player is on a node in a room, I want a reference to that rooms methods.
Example:
Say the character is in a room on a node with type enum of Elevator. The nodes in that room when a character is on one of them tells the elevator (there is more than one, so I have to reference the relevant elevator platform game object) to come to that floor as someone is waiting. Like this :
This is my character script pseudo code:
If currentNode.type == “Elevator”
currentNode.reference.CallElevator(currentNode.y)
A different node might have to open a door instead, so I couldn’t hardcode my reference because it had to be flexible depending on what I want the node to do when the character is on that node. Hope that explains my intentions.
I’ve no idea what the best way to implement this is, as people keep saying different things like, virtual and override inheritance, dynamic type, interfaces and using generics… I’m no closer to knowing what’s the right way to do this. If anything the more I Google the more confused I get with the options I have to choose from.
Now that you have defined the problem better I would suggest using inheritance or an interface. There are advantages and disadvantages for both.
Start with using an Interface. If that is not powerful enough then move to something else.
// Interface
public interface IRoom {
void UseRoom ();
}
// Node class
public class Node : IHeapItem<Node> {
public int x;
public int y;
public IRoom reference;
...
}
// An example room
public class Elevator : IRoom {
public void UseRoom (){
CallElevator ();
}
}
// A different room
public class DrinkingFountain : IRoom {
void UseRoom (){
DrinkFromFountain();
}
}
Thanks for this, looks like what i need, just a question about it. Is there a way to i can control what method to call ? For example say depending character’s thirst level i would want DrinkFromFountain, or may want a different method to do something different. It seems currently i am stuck with having to call one method only per node.
That or i don’t quite understand how to make it more flexible with different methods related to the reference depending on the situation.
Question… are these being set up through the inspector, or via code?
If it’s in the inspector, it sounds like you want a ‘UnityEvent’.
If it’s via code, it sounds to me like you want a delegate.
It’s not the object you’re concerned about, it’s the method on the object you’re concerned about. Both of those options allow you to reference methods (functions) on objects. The primary difference is UnityEvent is serializable and editable via the inspector.
I never use inspector, i prefer being in control with the code - in the long term it helps me guarantee everything is instantiated in the right order when i set up references.
The methods are some times related to a given object though aren’t they? Like, drinking fountain or elevator is specific to that particular GO which was why the reference solved that issue, as i can assign the reference as i create the object in the world in Start etc. Is a delegate a different thing to using an interface or compliments it?
How are you going to select between the various actions? If its something your player or an AI can select I would follow a completely different structure.
I get the strong feeling anyway that you need to take a step back and consider the overall structure of your game. There are a bunch of questions still outstanding that make me uneasy. Without seeing more of your design I would struggle to suggest a better structure. But it really feels like you are barking up the wrong tree with this approach*.
I get that feeling too because even with this interface suggestion, i am a bit confused how i get it to be referenced to a specific game object’s component method. Like if i have many drinking fountains, from the code provided, theres no link to say which drinking fountain.
I don’t know if this forums is the best place to go into detail of what i am trying to do or whether its beyond the scope of unity forums?