#This isn t tested and it still sets the
1 messages · Page 1 of 1 (latest)
so say you have this interface:
public IClickable {
void OnClicked();
}
We can implement this interface on objects like so:
public class UtilityObject : MonoBehaviour, IClickable {
public void OnClicked() {
// Player clicked this utility object
}
}
public class EquippableObject : MonoBehaviour, IClickable {
public void OnClicked() {
// Player clicked this equippable object
}
}
public class InventoryObject : MonoBehaviour, IClickable {
public void OnClicked() {
// Player clicked this inventory object
}
}
public class InspectableObject : MonoBehaviour, IClickable {
public void OnClicked() {
// Player clicked this inspectable object
}
}
Ohh, so like use it to call some event from the object itself?
You can do something like this instead of what you have in your screenshot:
void Update(){
ray = cam.ScreenPointToRay(Input.mousePosition);
if(Physics.Raycast(ray, out RaycastHit hit)){
IClickable clickable = hit.transform.GetComponent<IClickable>();
if(clickable != null) {
clickable.OnClicked();
}
}
}
this is significantly more performant and maintainable
leverage the power of polymorphism! 🌩️
So, I have some issues with that. 1, this should happen when it's hovered over, not clicked. 2, it's kinda weird from a data design perspective to have every single object contain a script just to change the cursor
- okay, the naming is not relevent, you can just rename it to OnHover
Ah. For some reason I thought that would lock me into that
the functionality is literally the same, it's just names of stuff
- this route allows you to extend functionality in the future. if you're ONLY looking to change the cursor. but i imagine if you're looking to have a cursor change on hover, you'll probably want cursor change on unhover, and interactions on click, or click and drag, etc.
Yeah, I know better. Not sure why I thought that
if you're ONLY looking to change cursor on hover, you could just use a dictionary
Dictionary<string, Sprite>
where string is the tag
that would be performant enough
but you could also extend the interface or use a dictionary of types
Dictionary<Type, sprite> typeCursorSprites;
and in your code:
cursor.sprite = typeCursorSprites[typeof(clickable)];
I do want you to be able to left and right click to inspect or use objects, but I figured I'd use OnMouseDown, which doesn't exist for hovering. Clicking functionality has very little to do with the hovering, as well
You lost me with that one
With an interface, it'd just be the same thing, right? I'd just use OnMouseDown? No reason to have an OnClicked function called from another script when Unity has one ready-built
yes you're right
If I stuck with the current approach, I would have one main script handling hovering stuff, and one on all the objects with the clicking stuff
i was simply using interfaces to get you to thinking down the right path when it comes to using interfaces and polymorphism rather than massive switch statements
Actually, now that I'm thinking of it...
Look at this page:
there are a bunch of functions for "OnMouse"
the idea is the same though, leverage that every object is a MonoBehaviour and skip using tags or switch statements
Wouldn't the same objects have hovering as have clicking functionality? So in theory, using an interface would be ideal for that, so objects don't show that they can be clicked (what the cursor shows) but not actually have any clicking functionality
yes
exactly
trust me, doing it this way
is 10000000% more maintainable
it's also more performant
use an interface, define any common methods to clickable objects in that interface
then define classes that implement that interface
it seems odd to have so many classes for now, but you're saving yourself alot of hassle in the future
Oh hey wait, OnMouseEnter is what I was talking about. OnMouseDown for hovering. So I have my hovering and my clicking right there
yes you can use those methods i mentioned. the only worry is if two objects get hovered over on the same frame
Yeah, I think you've convinced me
but that's an edge case im sure you cna handle
Thank you a ton
👍 good luck.
one more thing i'll leave you with
i knew right away you needed to restructure your code when i saw your switch statements. we say code "smells" when you're doing something in a way that it shouldn't
if you're interested in optimizing and getting better at coding, look into design patterns
you'll use them daily as a game programmer
^ a really great resource
Oh yeah, I knew that was done poorly but thought I pretty much ruled out my other options
Is it possible to have an interface contain "predefined" code? Something like the interface calling Cursor.SetCursor(newCursor, cursorHotspot, CursorMode.Auto); with its own cursor by just doing SetCursor(utility) or whatever?
yep! they're called abstract classes
that's why i was mentioning them before
look into them and learn what they are, you'll use them alot
Okay, so that's what those are
I speedread that page you sent a few times and couldn't figure it out. I'll have to take a deeper look
public abstract class ClickableObject : MonoBehavior {
[SerializeField] protected Sprite cursorHoverSprite;
public virtual void OnMouseHover(Cursor cursor){
Cursor.SetCursorSprite(cursorHoverSprite);
}
public abstract void OnMouseClick();
}
for example
public class UtilityObject : ClickableObject {
public override void OnMouseClick() {
...
}
}
Wait, do I just define these abstract classes in my GameManager script then?
Oh, are they their own script?
I'm just gonna find a video on them real quick, actually
Thank you again!
essentially you need to know, in an abstract class:
- if a method is marked as "virtual", then the abstract class can provide an implementation, and any classes that derive from the abstract class can override that method.
- if a method is marked as "abstract", then the abstract class CANNOT provide an implementation, and any classes that derive from the abstract class MUST override that method and provide a implementation
they go in their own script file