Armageddon
Level 6
|
|
« on: March 20, 2015, 09:19:50 PM » |
|
So I've been struggling with this for awhile. I have a system in place already but I feel like there's gotta be a simpler way.
So it's a first person game. My system involves three scripts. Raycast.cs, Useable.cs, and Object.cs.
The raycast script just shoots a ray from the camera's forward and gets a collider. If that collider has the right tag name and a Usable.cs script it will use a function in it called OnUse().
The useable script is meant to be attached to objects with the Object.cs script. It has a longish switch statement to check which Object.cs script is on the GameObject at scene load. The switch statement uses GetComponent<Object.csType>();. Then it has an OnUse() function that calls the Object.cs OnUse() function.
There are many Object.cs scripts, they all just have an OnUse() function and do things. There's a Button.cs, Cigarette.cs, etc. And the Useable.cs script is checking all of them and then using them.
I think this is faster than checking for the dozen+ types of object scripts every interaction so it just happens once on scene load. But I'd rather just call an OnUse() function from the raycast script without having to check the component since all the scripts use the same Function name.
Any ideas?
|
|
|
Logged
|
|
|
|
BorisTheBrave
|
|
« Reply #1 on: March 21, 2015, 02:08:16 AM » |
|
Two ways: - Use SendMessage - Use inheritance or interfaces.
|
|
|
Logged
|
|
|
|
nickgravelyn
Guest
|
|
« Reply #2 on: March 22, 2015, 07:47:02 AM » |
|
I second the above suggestion of SendMessage. Once you have your target object it's just: targetObj.SendMessage("OnUse", null, SendMessageOptions.DontRequireReceiver);
The last argument means to not raise exceptions if the target object doesn't have that method. The only downside of SendMessage is that it can only pass one parameter, but for your situation it sounds like that'd be fine.
|
|
|
Logged
|
|
|
|
|
nickgravelyn
Guest
|
|
« Reply #4 on: March 22, 2015, 11:53:09 AM » |
|
While true it's "slow", that just means it's not something you want firing off many times each frame. For events like this where you're sending one message once every few seconds I'd say it's a great way to keep the architecture simple.
|
|
|
Logged
|
|
|
|
|
Brainswitch
|
|
« Reply #6 on: April 06, 2015, 04:41:10 AM » |
|
The only downside of SendMessage is that it can only pass one parameter, but for your situation it sounds like that'd be fine.
Another downside IMO is that it uses strings for function names, which causes issues such as typos not being caught by the compiler and renaming/refactoring code more annoying.
|
|
|
Logged
|
|
|
|
Layl
|
|
« Reply #7 on: April 06, 2015, 05:48:06 AM » |
|
Since it's C# you could as well make an extension method to make your own type-safe alternative to SendMessage. With a bit of reflection jiggerypokery you could make a method that can be used like this. // Signature public static T Send<T>(this GameObject obj);
// In your code gameObject.Send<IUsable>().Use();
The overhead of creating a new IUsable implementing class at runtime just as a shim to call Use() on all components might be a bit much though. Edit: Alternatively you can do this to avoid the create-a-class-at-runtime. // Signature public static void Send<T>(this GameObject obj, Action<T> call);
// In your code gameObject.Send<IUsable>(u => u.Use());
|
|
|
Logged
|
|
|
|
Hyiero
Level 0
|
|
« Reply #8 on: April 06, 2015, 07:14:42 AM » |
|
Sounds like your Objects.cs is a perfect example of an abstract class because nothing can just be a "Object" it has to be more defined, such as a "cigarette", which inherits from Object.cs.This would allow for you to call just targetObject.OnUse() in the raycast script.
|
|
« Last Edit: April 06, 2015, 08:59:31 AM by Hyiero »
|
Logged
|
|
|
|
Layl
|
|
« Reply #9 on: April 06, 2015, 11:02:14 AM » |
|
Sounds like your Objects.cs is a perfect example of an abstract class because nothing can just be a "Object" it has to be more defined, such as a "cigarette", which inherits from Object.cs.This would allow for you to call just targetObject.OnUse() in the raycast script.
No need for an entire abstract class here, an interface should be fine.
|
|
|
Logged
|
|
|
|
nickgravelyn
Guest
|
|
« Reply #10 on: April 06, 2015, 05:39:29 PM » |
|
Sounds like your Objects.cs is a perfect example of an abstract class because nothing can just be a "Object" it has to be more defined, such as a "cigarette", which inherits from Object.cs.This would allow for you to call just targetObject.OnUse() in the raycast script.
No need for an entire abstract class here, an interface should be fine. to this. In C# you can only have one parent class but you can implement any number of interfaces. Definitely choose interfaces over subclassing where possible.
|
|
|
Logged
|
|
|
|
|