My game will have various objects, like signs, NPCs, doors, etc… All of these objects will be tagged with the “Interactive” tag and have the “InteractiveObject” script. This script has the “Act()” function. The player is in first person camera, and interacts with these objects by using raycast to check if the player is looking at any “Interactive” object. If the player is looking at any of them and clicks with the mouse button, the function “Act()” of the raycasthit “InterativeObject” script will be called.
However, each “Interactive” tagged object should have that same “InteractiveObject” script for my code to work, but the Act() of the object’s script should be different. A sign Act() would be different of the door Act(), for exemple. Here’s the code that runs the object’s Act() function:
if(Physics.Raycast(raycast, out hit) && hit.collider.tag == "Interactive" && Input.GetButtonDown("Mouse 1")){
InteractiveObject function = (InteractiveObject)hit.collider.GetComponent(typeof(InteractiveObject));
function.Act();
}
So, is there a way that all of the “Interactive” tagged objects can have the same script “InteractiveObject” but with a diferent behavior to the Act() function in each instance of the script? Is that even possible, or am I approaching the problem the wrong way? If that’s the case, can you guys point in the right direction? =/
you can extend InteractiveObject for each different objet you like, and override the Act function.
To do this, you will first need to add the virtual keyword to the method signature of your InteractiveObject class.
Then for each different type of interactive object, define a new class than extends InteractiveObject, and overrides the Act() method.
For example, your door Act might look something like:
public class InteractiveDoor : InteractiveObject {
public override void Act() {
// your specific door functionality
}
}
This way, you can then attach the InteractiveDoor, or InteractiveSign or whatever to each object, and have its specific Act() functionality while keeping whatever other functionality exists in the InteractiveObject sript. (BTW you would not attach the InteractiveObject script to your gameobjects, only the child InteractiveDoor or InteractiveSign script.
However, if there is no common functionality that exists in the InteractiveObject script, then it may be simpler just to have different scripts for each object with an Act() method and use gameObject.SendMessage("Act"); to fire off the functionality.
var obj = hit.collider.GetComponent(typeof(InteractiveObject));
var fn = obj.GetType().GetMethod("Act", BindingFlags.Public | BindingFlags.Instance);
var fnParams = new object[]{ "FirstParam", 10, true, etc... };
if (fn != null)
{
fn.Invoke(obj, fnParams );
}
This will invoke ‘Act’ on any object returned by the GetComponent method. Hence it could run on any object returned by GetComponent.
Note: This is pretty much what Unity will be doing internally when you use the SendMessage() method - But this may be slightly more efficient [Disclaimer: I don’t know!]
Edit: Just to clarify - You could use this if you don’t want to use inheritance / overriding as suggested above (probably your best bet…) For example you could call a differently named method based on the actual type of the object that GetComponent returns.
Thanks for all your answers. I have never seen the SendMessage() method before, i am still new to Unity, sounds interesting… And I have though about the all act() in one and check by the name of the hit wich act() should be called, i just didn’t know if that was the best sotulion. It’s a valid option i will look into though.
I am a little busy at the moment, but now that i have a clearer vision of what can be done, I will try your sugestions and see which runs best for me when I can. Thanks a lot guys.