Wayback Machinekoobas.hobune.stream
May JUN Jul
Previous capture 13 Next capture
2021 2022 2023
1 capture
13 Jun 22 - 13 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
0
Question by Ohanniganswife · Jul 01, 2015 at 09:49 PM · c#collisionraycastraycasting

What's a reliable way to detect if an object is no longer being hit by a ray?

I'm aware raycasts are event driven and that colliders can't physically detect if they're being hit by a ray, and I'm aware of a way around it by sending a message to whatever a ray hits and keeping an object of its last hit and sending a message to that cached object when the ray returns not hitting anything, but it doesn't seem to be working 100% of the time.

 void CreateRay(Ray ray, float length)
     {
         if(Physics.Raycast (ray, out hit, length))
         {
             if(lastHit == null)
                 lastHit = hit.collider.gameObject;
             if(lastHit != null && lastHit != hit.collider.gameObject)
             {
                 lastHit.SendMessage("NotHitByRay", 0, SendMessageOptions.DontRequireReceiver);
                 lastHit = hit.collider.gameObject;
             }
             lr.SetPosition (1, hit.point);
             ReflectionInfo ri = new ReflectionInfo(ray.direction, hit);
             if(hit.collider.gameObject.tag == "reflector")
             {
                 hit.collider.gameObject.SendMessage("HitByRay", ri, SendMessageOptions.DontRequireReceiver);
             }
 
         }
         else
         {
 
             if(lastHit != null)
                 lastHit.SendMessage ("NotHitByRay", 0, SendMessageOptions.DontRequireReceiver);
             lastHit = null;
             lr.SetPosition (1, start+(direction * 20f));
         }
 
     }

You can see I'm redundant about sending the NotHit message only because I still can't make it trigger all the time.

This is the receiver

 void HitByRay(ReflectionInfo info)
     {
         reflectInfo = info;
         if (!active) {
             reflect ();
             active = true;
         }
     }
     
     void NotHitByRay(int num)
     {
         Destroy (reflection);
         active = false;
     }

The main issue is NotHitByRay is not beingcalled, and the laser reflections persist when the source laser stops hitting the object. IDK, is there an approach I am not seeing that could make it work?

Comment
Add comment · Show 1
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 meat5000 ♦ · Jul 01, 2015 at 09:50 PM 0
Share

@Ohanniganswife Please reaccept AlwaysSunny's answer. I had to unselect it to solve an error in moderation. I could re-check it myself but you'd lose out on your 5 karma.

1 Reply

· Add your reply
  • Sort: 
avatar image
0

Answer by AlwaysSunny · Jun 30, 2015 at 07:07 PM

Don't use SendMessage. Just make the method public, get the receiver component, and invoke the method on it. Vastly superior.

 public void HitByRay(){}
 
 Receiver receiver = hit.collider.GetComponent<Receiver>() as Receiver;
 if (receiver) receiver.HitByRay();


"keeping an object of its last hit and sending a message to that cached object when the ray returns not hitting anything"

This is not foolproof. Not without a good bit of case-planning and forethought. Caching the object and sending a "not hitting something" event might seem like a smart optimization, but comes with complications that make it unfavorable, which you're obviously witnessing.

Just invoke the receiver method on the hit object each frame. This is not really more expensive in this particular situation, and should be 100% foolproof.

Generally this means changing your logic around a bit. You're creating the equivalent of an "OnRaycastStay" event instead of Enter/Exit events. Enter/Exit events can be done, but you have to plan for every possible contingency. In many if not most cases, the performance gain isn't worth it. Sounds like a breeding ground for bugs to me, unless you know exactly what you're doing.

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 Ohanniganswife · Jun 30, 2015 at 07:24 PM 0
Share

Yeah I think one of the main issues is with what I'm doing which is hard to explain but it uses a static method to shoot out a loop of rays, and if a ray hits something, if that object is a reflector, the reflector creates a new prefab laser reflection, etc. Originally I just had it so the initial laser handled all the reflections, but a function I want is to make it so once an object is reflecting 1 laser, it can't reflect anymore. That's where I'm having trouble, because if the object doesn't get triggered that it's no longer reflecting, then it just has lingering reflections despite no source. I can make infinite reflections happen easily, it's just that single reflection only I can't seem to get the logic down for. I did what you suggested but it's the same result, lingering reflections when a ray stops hitting. ID$$anonymous$$

I think handling all the reflections from the initial laser will probably end up being better, and I will just have to find a different way to make it so if it's hitting an object that already has a reflection, then it should not reflect. I just already have kind of convoluted code at the laser source, so I wanted to spread that out

avatar image AlwaysSunny · Jun 30, 2015 at 07:35 PM 1
Share

To satisfy the "only accept one" requirement:
$$anonymous$$anage a variable that detects whether the reflection method has been tripped this frame, and disallow additional attempts.

 public void HitByRay(){
   if (isHit) return;  // leave here if already hit this frame  
   isHit=true;  // set the bool to indicate got hit this frame
 }
 
 void LateUpdate() {
   isHit=false;  // reset the variable at the end of the frame
 }


To satisfy the "need exit event" requirement:
You can have a variable recording whether you were hit last frame as well. $$anonymous$$easuring the difference between the two can serve as an Enter / Exit event.

 if (isHit && !wasHit) // enter
 if (!isHit && wasHit) // exit

Regarding the fact that you're still having an issue with the "exit" event, I mentioned this is an "OnRaycastStay" approach - your logic would need to change to accommodate that.

avatar image Ohanniganswife · Jun 30, 2015 at 07:49 PM 0
Share

Ok thanks I'll try these out. $$anonymous$$y main disconnect in the logic was on what order things were happening in each frame because of how convoluted my current code is since a lot of it is handled outside of an Update and or it's spread out between multiple classes and I'm trying to interlink it together causing me to get lost in the spread out logic.

avatar image AlwaysSunny · Jun 30, 2015 at 07:51 PM 0
Share

This might be a handy document to review:
http://docs.unity3d.com/$$anonymous$$anual/ExecutionOrder.html

Best, :)

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

4 People are following this question.

avatar image avatar image avatar image avatar image

Related Questions

How to check if a raycast is not hitting any tagged colliders? 0 Answers

How to render a lot of the same small objects 2 Answers

Is it possible to check how much a trigger is filled by %? 1 Answer

c# How do I set up continuous raycast collision detection? 1 Answer

Raycast goes through 1 Answer


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