Welcome, Guest. Please login or register.

Login with username, password and session length

 
Advanced search

1411487 Posts in 69371 Topics- by 58427 Members - Latest Member: shelton786

April 24, 2024, 12:05:55 PM

Need hosting? Check out Digital Ocean
(more details in this thread)
TIGSource ForumsDeveloperTechnical (Moderator: ThemsAllTook)Interaction System
Pages: [1]
Print
Author Topic: Interaction System  (Read 1411 times)
Armageddon
Level 6
*



View Profile
« 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
Level 10
*****


View Profile WWW
« 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:

Code:
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
Gunhead
Level 0
**


View Profile WWW
« Reply #3 on: March 22, 2015, 08:52:20 AM »

SendMessage is pretty slow from what I remember, so only good for trivial one offs. Every game I make now I implement some sort of event system right into it, including in Unity.

http://stackoverflow.com/questions/4574016/game-objects-talking-to-each-other
Logged

nickgravelyn
Guest
« Reply #4 on: March 22, 2015, 11:53:09 AM »

SendMessage is pretty slow from what I remember, so only good for trivial one offs. Every game I make now I implement some sort of event system right into it, including in Unity.

http://stackoverflow.com/questions/4574016/game-objects-talking-to-each-other
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. Smiley
Logged
cc21
Level 0
*


View Profile
« Reply #5 on: March 23, 2015, 06:13:06 AM »

Code:
Button.cs
interface IUsable { void OnUse(); }
class Button: MonoBehaviour, IUsable { void OnUse() { press_button(); } }

Raycast.cs
if (Raycast (origin, direction, out hitInfo, distance, layerMask) ) {
IUsable c;
if ((c = hitInfo.collider.gameObject.GetComponent(typeof(IUsable) as IUsable)) != null)
c.OnUse();
}
« Last Edit: March 23, 2015, 06:18:35 AM by cc21 » Logged
Brainswitch
Level 0
**



View Profile WWW
« 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
Level 3
***

professional jerkface


View Profile WWW
« 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.

Code:
// 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.
Code:
// 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
*


View Profile
« 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
Level 3
***

professional jerkface


View Profile WWW
« 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.
Hand Thumbs Up Left 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
Pages: [1]
Print
Jump to:  

Theme orange-lt created by panic