Wayback Machinekoobas.hobune.stream
May JUN Jul
Previous capture 12 Next capture
2021 2022 2023
1 capture
12 Jun 22 - 12 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 a5exiadz2019 · May 08, 2019 at 01:22 PM · scripting problemraycastframerate

Raycast consuming too much ! (VR)

Hi !

I am trying to make a "UI interaction system" using a raycast in my VR project and here is what I came up with :

I use a raycast from a start point (from the hand/controller on 5 meters maximum) and check if it collides with anything with the "UIElement" Tag. If so, it displays a line (so the user can see where he is aiming). It also checks if the gameobject that was hit by the raycast has a Button component and, if it has one and the player presses the trigger, it calls the button's onClick() method.

All of this is used into a method that is called constantly in the FixedUpdate. But I have a huge problem. Since VR needs a good 75-90 FPS to run smoothly, I can't afford the fps drop that occurs with my solution. So what happens is that everything runs correctly, until I aim at a UIElement and the line appears. And at that point, I go from a constant 90 FPS to 45-62 FPS.

What can I do to improve this ?

In the profiler, here is what I got :

alt text



     void FixedUpdate()
     {
         RayForUI();
     }
 
     //-------------------------------------------------
 
 
     private void RayForUI()
     {
         RaycastHit hit;
 
         LineRenderer rayLine = rayCastStartPoint.parent.GetComponent<LineRenderer>();
 
         Physics.Raycast(rayCastStartPoint.position, rayCastStartPoint.forward, out hit, raycastMaxDistance, RaycastCollidableLayers);
 
         if (hit.collider != null)
         {
             if(hit.collider.CompareTag("UIElement"))
             {
                 Button bt = hit.collider.GetComponent<Button>();
 
                 rayLine.colorGradient = GradColor(); //just a method to set a gradient to the line
                 rayLine.startWidth = lineWidthStart;
                 rayLine.endWidth = lineWidthEnd;
 
                 Debug.Log(hit.collider.name);
 
                 Debug.DrawRay(rayCastStartPoint.transform.position, rayCastStartPoint.forward * hit.distance, Color.blue);
 
                 Vector3 endPos = hit.point;
 
                 rayLine.SetPositions(new Vector3[] { rayCastStartPoint.position, endPos });
 
                 rayLine.enabled = true;
 
                 if (bt != null)
                 {
                     Button button = hit.collider.GetComponent<Button>();
                     ColorBlock colors = button.colors;
                     colors.normalColor = HoverONColor;
                     button.colors = colors;
 
                     if (SteamVR_Input._default.inActions.GrabPinch.GetStateUp(hand))
                     {
                         bt.onClick.Invoke();
                     }
                 }
                 else //here, It is supposed to reset the color of the button when I don't hover over it (but I think it a little overhead) what do you suggest ?
                 {
                     Button button = this.gameObject.GetComponent<Button>();
                     ColorBlock colors = button.colors;
                     colors.normalColor = HoverOFFColor;
                     button.colors = colors;
                 }

1.png (134.2 kB)
Comment
Add comment
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

2 Replies

· Add your reply
  • Sort: 
avatar image
1

Answer by xxmariofer · May 08, 2019 at 01:57 PM

well lets go little by little, since what is consuming your resources isnt the ray

create the linerenderer ooutside the method and cast it in the start, using getcomponent is expensive.

 LineRenderer rayLine;

 void Start()
 {
    rayLine = rayCastStartPoint.parent.GetComponent<LineRenderer>();
 }

remove the button since is just the same as bt

is there any need to change the gradient color and size all the time? if its constant just set it in the start/awake event

 Button button = hit.collider.GetComponent<Button>();//REMOVE THIS LINE AND CHANGE button FOR bt

avoid changing the normal colors, getting a copy of the color block changing and re-change it is slower than just changing the Image.color (and should have the exact same effect) the last part of the code is a bit weird, if you dont hit a button what button color you reset? since if you are resetting the color of the button attached to to that script it makes me assume that ALL the buttons have the same script? or when you stop hovering you set a default button? i am lost there.

Comment
Add comment · 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
0

Answer by a5exiadz2019 · May 08, 2019 at 03:43 PM

@xxmariofer Thank you for your response. I was trying to fix it while waiting for answers and it went well, I think.

Now, the framerate is stable (~ 90 FPS). I did as you suggested. The rayline is setup in the Awake function (with its width and length). But what was really consuming was the Debug.Log stuff. As soon as I commented them, the framerate got stable again.

I also added an if statement before the Physics.raycast line, I've never understood why, but in the Unity Documentation, it is used this way, so I did the same and I guess it helped stabilizing the fps ?

About the last part, you're right. The script is attached to every button I want to interact with. I know, it's not optimal at all, but I coded this stuff yesterday, just straight forward, without second thoughts. Is it a problem if I leave it that way ? For now, it does what I want and doesn't seem ressources-taking.

I have two other minor problems tho ... the first one, is about the line that is rendered. It is supposed to disappear when the raycast doesn't collide with a "UIElement". But what it does right now, is that when the user doesn't aim at a "UIElement" anymore, the line is still there, but it is not attached to the controller. It's like it is floating at the last position known when the raycast was hitting the "UIElement".

This line is supposed to fix this, but it doesn't :

                 if (hit.collider.CompareTag("UIElement"))
                 {
                     rayLine.enabled = true;
                     //some code
                 }
                 else
                 {
                     rayLine.enabled = false;
                 }



alt text
The other problem : when I use the onClick.invoke() on a Smartphone UI that I created in the scene (the user can compose a number of 10 digits and call it) , it is supposed to be called once, when the user presses the trigger on the number he wants to add. He should be able to do so until he reachs the 10 digits limit, one number at a time, after each trigger pressure.

But for now, as soon as I press the trigger, the line is fullfilled with the same button that I pressed only once. So if I press the button "2" I got "2222222222" instead of just "2" on the number line.

My guess is that onClick is called multiple time and not juste once. Any solution for that ?

alt text



Here is my improved code btw :

     private LineRenderer rayLine;
 
     //=============================================== End of variables declaration ===============================================//
 
     private void Awake()
     {
         if (GetComponent<SteamVR_Behaviour_Pose>())
         {
             hand = GetComponent<SteamVR_Behaviour_Pose>().inputSource;
         }
 
         rayLine = rayCastStartPoint.parent.GetComponent<LineRenderer>();
         
         rayLine.colorGradient = GradColor();
         rayLine.startWidth = lineWidthStart;
         rayLine.endWidth = lineWidthEnd;
     }
 
     //Used when we need to do something with physics over time
     void Update()
     {
         RayForUI();
     }
 
     //-------------------------------------------------
 
 
     private void RayForUI()
     {
         RaycastHit hit;
 
         if(Physics.Raycast(rayCastStartPoint.position, rayCastStartPoint.forward, out hit, raycastMaxDistance, RaycastCollidableLayers))
         {
             if (hit.collider != null)
             {
                 if (hit.collider.CompareTag("UIElement") || hit.collider.CompareTag("Screen_BG"))
                 {
                     Button bt = hit.collider.GetComponent<Button>();
 
                     //Debug.Log(hit.collider.name);
 
                     //Debug.DrawRay(rayCastStartPoint.transform.position, rayCastStartPoint.forward * hit.distance, Color.blue);
 
                     Vector3 endPos = hit.point;
 
                     rayLine.SetPositions(new Vector3[] { rayCastStartPoint.position, endPos });
 
                     rayLine.enabled = true;
 
                     if (bt != null)
                     {                        
                         ColorBlock colors = bt.colors;
                         colors.normalColor = HoverONColor;
                         bt.colors = colors;
 
                         if (SteamVR_Input._default.inActions.GrabPinch.GetStateDown(hand))
                         {
                                 bt.onClick.Invoke();
                         }
                     }
                     else
                     {
                         if(GetComponent<Button>() != null)
                         {
                             Button button = this.gameObject.GetComponent<Button>();
                             ColorBlock colors = button.colors;
                             colors.normalColor = HoverOFFColor;
                             button.colors = colors;
                         }
          }



2.png (91.6 kB)
3.png (353.0 kB)
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 xxmariofer · May 09, 2019 at 08:27 AM 0
Share

physics.raycast returns true if it collides with something and false if it doesnt, so using the method inside the if saves you unneded comprobations of the collider etc since the if wont trigger when it didnt collide with anything. yes all logs and the editor low you fps, if you want to test the fps you should remove the logs andbuild the game for getting the real fps of the game. having that exact script in each button will affect a lot to the performance, it is creating the exact same ray for each button rather than just once, even if you needed a lot of different rays you should try having a raymanager. for the line issue you have 2 options, the vector3 from the pooints array and just give them their default value, or just desactivate the line likethis

 rayLine.gameObject.SetActive(true);

you will need to reactivate it whehenever you use it with this method. last your invoke issue is that you are calling the invoke every fixedupdate iteration so you are calling a lot oif times per second, i have never done vr but there should be something like onclick event in the S$$anonymous$$mVR_Input._default.inActions, if not you will have to add a bool called something like isPressed, set the ispressed value to true when you call invoke and only let the invoke be called when the ispressed is false, and set it again to false when you stop hovering the button

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

218 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image

Related Questions

Spawn script on mesh crashes Unity 0 Answers

How to move the main camera in Google Cardboard? 0 Answers

UI Text showing weird string value? 1 Answer

How to access scripts in other game object with raycasts? 2 Answers

Vertical distance indication 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