Wayback Machinekoobas.hobune.stream
May JUN Jul
Previous capture 13 Next capture
2021 2022 2023
2 captures
13 Jun 22 - 14 Jun 22
sparklines
Close Help
  • Products
  • Solutions
  • Made with Unity
  • Learning
  • Support & Services
  • Community
  • Asset Store
  • Get Unity

UNITY ACCOUNT

You need a Unity Account to shop in the Online and Asset Stores, participate in the Unity Community and manage your license portfolio. Login Create account
  • Blog
  • Forums
  • Answers
  • Evangelists
  • User Groups
  • Beta Program
  • Advisory Panel

Navigation

  • Home
  • Products
  • Solutions
  • Made with Unity
  • Learning
  • Support & Services
  • Community
    • Blog
    • Forums
    • Answers
    • Evangelists
    • User Groups
    • Beta Program
    • Advisory Panel

Unity account

You need a Unity Account to shop in the Online and Asset Stores, participate in the Unity Community and manage your license portfolio. Login Create account

Language

  • Chinese
  • Spanish
  • Japanese
  • Korean
  • Portuguese
  • Ask a question
  • Spaces
    • Default
    • Help Room
    • META
    • Moderators
    • Topics
    • Questions
    • Users
    • Badges
  • Home /
avatar image
1
Question by DavidDebnar · Feb 14, 2013 at 08:19 PM · collideronmousedownonmouseuponmouse

How can I call OnMouse functions on a specific collider?

Hello, A crazy idea/question that I've came up with past midnight incoming!

I was wondering if it was possible to call OnMouseEnter and similar functions on different colliders/gameObjects? Example:

 function ColliderOfADifferentObjectA.OnMouseOver () {
     isMouseOverTheColliderOfADifferentObjectA = true;    
 }
 
 function ColliderOfADifferentObjectB.OnMouseOver () {
     isMouseOverTheColliderOfADifferentObjectB = true;
 }

this of course doesn't work, but it's just an example to give you an idea of what I mean. There are workarounds I could use, but for a long time I've always had to create a second script that handles nothing but the OnMouse events and I'd welcome a cleaner solution than that.

--- David

Comment
Add comment · Show 5
10 |3000 characters needed characters left characters exceeded
▼
  • Viewable by all users
  • Viewable by moderators
  • Viewable by moderators and the original poster
  • Advanced visibility
Viewable by all users
avatar image Jeremy Hindle · Feb 14, 2013 at 08:26 PM 0
Share

Does the functionality have to be centrally controlled (in one or more of your "God" classes) or can the script be on the GameObject itself?

If it can be controlled in a separate script you could just (as I imaging from your description above you have) just add an On$$anonymous$$ouseEnter / On$$anonymous$$ouseOver event to it.

Otherwise there are some other ways you could do it using tags on gameobjects / GameObject name / other information on the gameobject which you can gather using a raycast.

avatar image DavidDebnar · Feb 14, 2013 at 08:28 PM 0
Share

It should be controlled by the god classes, because as I already stated, I don't want a $$anonymous$$onoBehaviour component on the collider/gameObject that the function is checking. Again, this is probably just a crazy idea I've came up with past midnight.

avatar image Loius · Feb 14, 2013 at 08:31 PM 0
Share

I haven't encountered any way to do that. Raycasts can point out an object but I don't think there's any way to fake a function like that.

avatar image DavidDebnar · Feb 14, 2013 at 08:36 PM 0
Share

That's what I am thinking. I'll probably just end up indexing the booleans of colliders in a dictionary and raycast.

avatar image Jeremy Hindle · Feb 14, 2013 at 09:05 PM 0
Share

Ive written an example... Yep I'd use an enum personally rather than a dictionary just to keep track of things more easily and make syntax more readable if you are going to have lots of objects.

2 Replies

· Add your reply
  • Sort: 
avatar image
1
Best Answer

Answer by DavidDebnar · Feb 22, 2013 at 02:04 PM

This is what I ended up doing. It works on desktop and mobile (mouse and touch control).

This code calls "OnActive" and "OnHover" functions instead of OnMouseDown, so a receiver would look like this:

 public var isMouseOver : boolean = false;
 public var isMouseDown : boolean = false;
 
 function OnHover (isHovered:boolean) {
     isMouseOver = isHovered;
 }
 
 function OnActive (isActive:boolean) {
     isMouseDown = isActive;
 }

The code (JS, I can provide a C# version, if anyone would want):

 #pragma strict
 
 public var UICamera : Camera;
 public var isMobile : boolean = false;
 
 private var lastCollider : Collider;
 
 function Awake () {
 
     if(Application.platform == RuntimePlatform.IPhonePlayer || Application.platform == RuntimePlatform.Android)
         isMobile = true;
     else
         isMobile = false;
 }
 
 function Update () {
 
     var clickPosition : Vector2 = Vector2.zero;
 
     if(isMobile) clickPosition = Input.touches[0].position;
     else clickPosition = Input.mousePosition;
 
     var ray : Ray = UICamera.ScreenPointToRay(clickPosition);
     var hit : RaycastHit;
 
     var didHit : boolean;
 
     if(!isMobile || Input.touches.length > 0)
         didHit = Physics.Raycast(ray,hit,10,1<<8);
 
     if(didHit) {
         if(hit.collider != lastCollider || lastCollider == null) {
 
             if(lastCollider != null) {
                 lastCollider.gameObject.SendMessage("OnActive",false);
                 lastCollider.gameObject.SendMessage("OnHover",false);
             }
 
             lastCollider = hit.collider;
 
             lastCollider.gameObject.SendMessage("OnHover",true);
         }
 
     }
     else if(lastCollider != null) {
         lastCollider.gameObject.SendMessage("OnActive",false);
         lastCollider.gameObject.SendMessage("OnHover",false);
 
         lastCollider = null;
     }
 
     if(lastCollider != null) {
         if((!isMobile && Input.GetMouseButtonDown(0)) || (isMobile && Input.touches[0].phase == TouchPhase.Began))
             lastCollider.gameObject.SendMessage("OnActive",true);
         else if((!isMobile && Input.GetMouseButtonUp(0)) || (isMobile && Input.touches[0].phase == TouchPhase.Ended))
             lastCollider.gameObject.SendMessage("OnActive",false);
     }
 }

This code uses SendMessage each time a button was hovered, clicked or released, so it could get quite heavy on a mobile device. To solve this, you could create a Collider-Receiver Component dictionary and instead of calling SendMessage on the collider (gameObject), use the collider as the key in the dictionary to get the reference to the component and call OnActive(true/false)/OnHover(true/false) on it.

Code to do this, assuming each clickable element is tagged with "GUI":

 import System.Collections.Generic;
 //...
 private var GUIElements : Dictionary.<Collider,ReceiverComponent>;
 //...
 function Start () {
     GUIElements = new Dictionary.<Collider,ReceiverComponent>();
     var allGUIElements : GameObject[] = GameObject.FindGameObjectsWithTag("GUI");
     for(var GUIElement : GameObject in allGUIElements)
         GUIElements[GUIElement.collider] = GUIElement.GetComponent(ReceiverComponent);
 }
 //...
 //Replace each SendMessage call with:
 GUIElements[lastCollider].IsActive(true);


-- David

Comment
Add comment · Show 1 · Share
10 |3000 characters needed characters left characters exceeded
▼
  • Viewable by all users
  • Viewable by moderators
  • Viewable by moderators and the original poster
  • Advanced visibility
Viewable by all users
avatar image primus88 · May 30, 2013 at 09:30 AM 0
Share

Hello $$anonymous$$,

I really like your ideas which I found here :

I need it to cast spells in my game. The view is an RTS style game and what I need is to just cast anywhere I want my spell by mouse click, detect if any collider is present and apply damage.

Does your JS cover this ? If so, can you provide a C# script as well? Your help would be much appreciated, as I am really new at coding and I stumbled for some time over this particular problem.

Thank you !

avatar image
0

Answer by Jeremy Hindle · Feb 14, 2013 at 09:02 PM

If you don't want to put an OnMouseOver() script on each GameObject you can do what you want with a single raycast in Update():

Draw a raycast out from the mouse:


  Ray ray = Camera.main.ScreenPointToRay(Input.mousePosition);



Then in update check if it hits anything:


 if (Physics.Raycast(ray.origin, ray.direction, out ObjectHitByMouseRaycast, 2000))
         {
 
 
         }



Then if it does hit something add checks in for what it's hit. Below I am checking the gameobject name as an example but you can really check anything about it:


         if (Physics.Raycast(ray.origin, ray.direction, out ObjectHitByMouseRaycast, 2000))
         {
             if (ObjectHitByMouseRaycast.collider.gameObject.name == "This")
             {
                 Debug.Log("Im over 'This'");
             }
 
             if (ObjectHitByMouseRaycast.collider.gameObject.name == "That")
             {
                 Debug.Log("Im over 'That'");
             }
         }



Here is a working example if you put this script anywhere in your scene and make a couple of game objects called "This" and "That" you can test it out:


 public class MouseRaycastDetector : MonoBehaviour {
 
     RaycastHit ObjectHitByMouseRaycast;
     // Update is called once per frame
     void Update () 
     {
 
         Ray ray = Camera.main.ScreenPointToRay(Input.mousePosition);
 
         if (Physics.Raycast(ray.origin, ray.direction, out ObjectHitByMouseRaycast, 2000))
         {
             if (ObjectHitByMouseRaycast.collider.gameObject.name == "This")
             {
                 Debug.Log("Im over 'This'");
             }
 
             if (ObjectHitByMouseRaycast.collider.gameObject.name == "That")
             {
                 Debug.Log("Im over 'That'");
             }
 
         }
         
     }
 }



If you are going to have a lot of objects I suggest you create an enum or a dictionary of the things you will test against to make things easier to keep track of and maintain.

Hope that helps.

Comment
Add comment · Show 4 · Share
10 |3000 characters needed characters left characters exceeded
▼
  • Viewable by all users
  • Viewable by moderators
  • Viewable by moderators and the original poster
  • Advanced visibility
Viewable by all users
avatar image DavidDebnar · Feb 14, 2013 at 09:56 PM 0
Share

Yes, I'll probably end up going with something similar. I'll work on the solution more tomorrow and will answer if I find any interesting solution that might be worth sharing ;)

avatar image Tarlius · Feb 22, 2013 at 02:40 PM 0
Share

A simple solution for a lot of objects might be to just put them in another layer. On that note, it might be an idea to make a public/serialised Layer$$anonymous$$ask you can tweak in the editor ins$$anonymous$$d of hardcoding it. That way it will be easier to change later/reuse.

avatar image DavidDebnar · Feb 23, 2013 at 10:43 PM 0
Share

$$anonymous$$y solution only uses a single layer, for faster raycasting and it'd be easy just to create a variable ins$$anonymous$$d of a harcoded bit shift value.

avatar image Tarlius · Feb 24, 2013 at 06:19 AM 0
Share

I don't think doing two layers is any slower than one, assu$$anonymous$$g the number of objects is the same, although I could be wrong? But I meant that by using separate layers you could just put only the things you want to "test against" ins$$anonymous$$d of an enum or dictionary/etc.

Your answer

Hint: You can notify a user about this post by typing @username

Up to 2 attachments (including images) can be used with a maximum of 524.3 kB each and 1.0 MB total.

Follow this Question

Answers Answers and Comments

13 People are following this question.

avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image

Related Questions

OnMouseDown() not called on child object collider 2 Answers

Text popup onMouseDown 2 Answers

OnMouseDown() won't work unless gameObject's 2DBox Collider - ‘Is Trigger’ is toggled on/off mid-game in editor. 0 Answers

Clickable area problem? 0 Answers

Accessing colliders, in if statement 2 Answers


Enterprise
Social Q&A

Social
Subscribe on YouTube social-youtube Follow on LinkedIn social-linkedin Follow on Twitter social-twitter Follow on Facebook social-facebook Follow on Instagram social-instagram

Footer

  • Purchase
    • Products
    • Subscription
    • Asset Store
    • Unity Gear
    • Resellers
  • Education
    • Students
    • Educators
    • Certification
    • Learn
    • Center of Excellence
  • Download
    • Unity
    • Beta Program
  • Unity Labs
    • Labs
    • Publications
  • Resources
    • Learn platform
    • Community
    • Documentation
    • Unity QA
    • FAQ
    • Services Status
    • Connect
  • About Unity
    • About Us
    • Blog
    • Events
    • Careers
    • Contact
    • Press
    • Partners
    • Affiliates
    • Security
Copyright © 2020 Unity Technologies
  • Legal
  • Privacy Policy
  • Cookies
  • Do Not Sell My Personal Information
  • Cookies Settings
"Unity", Unity logos, and other Unity trademarks are trademarks or registered trademarks of Unity Technologies or its affiliates in the U.S. and elsewhere (more info here). Other names or brands are trademarks of their respective owners.
  • Anonymous
  • Sign in
  • Create
  • Ask a question
  • Spaces
  • Default
  • Help Room
  • META
  • Moderators
  • Explore
  • Topics
  • Questions
  • Users
  • Badges