• 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 /
This question was closed Apr 18, 2015 at 03:05 PM by YoungDeveloper for the following reason:

Comment in existing question.

avatar image
0
Question by Abacab · Apr 18, 2015 at 02:59 PM · c#cameraraycastraycasthit

RE: RaycastHit and camera through walls

Original question

So the camera now reacts to the walls, but when it does, it starts "crawling" down the wall (when I reverse towards it) until it hits the ground and then it moves through the wall.

 void LateUpdate() {
 
 RaycastHit wallHit = new RaycastHit ();
         Ray wallRay = new Ray (camera.transform.position, car.transform.position - camera.transform.position);
         
         if (Physics.Raycast (wallRay, out wallHit, distance)) {
             if (wallHit.collider.tag == "Wall") {
                 camera.transform.position = wallHit.point;
             }
         }
 }

Comment
Add comment · Show 28
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 Glurth · Apr 18, 2015 at 03:16 PM 1
Share

You are currently resetting the position of the camera every LateUpdate that you detect contact with the wall. I suspect you want to add a flag, and use it to only reset the position the FIRST update that you contact the wall. Obviously, reset this flag when contact with the wall is broken.

This reason this is happening is because your "car" transform is below the camera, so the hit-point on the wall is below the camera. It may be coincidentally stopping when it reaches the floor, but I'd bet,it's actually stopping when it reached the car's y position.

Another way to eli$$anonymous$$ate this effect would be to eli$$anonymous$$ate the Y axis when you create your ray. ($$anonymous$$odify a local copy of car's position to be at the same y coordinate as camera's position- so neither one is below the other. Use this modified vector when creating your ray.) Note: Using a horizontal ray like this would allow the camera to pass over walls that are shorter than the camera is high.

avatar image Glurth · Apr 18, 2015 at 03:24 PM 1
Share

@YoungDeveloper, I think this should be a separate question. If he had not included a link to the other question, would you have closed it?

avatar image YoungDeveloper · Apr 18, 2015 at 03:36 PM 0
Share

You are telling me that this is so completely different that worth creating separate thread for that? And yes, i would close it, i always check users questions before answering, so there no way his previous post would get past me.

avatar image Glurth · Apr 18, 2015 at 03:40 PM 1
Share

Yes, that's exactly what I was saying, but that's just my opinion. Ok, as you wish.

avatar image Abacab · Apr 18, 2015 at 03:41 PM 0
Share

Thank you for your input Glurth!

avatar image Glurth · Apr 18, 2015 at 03:44 PM 1
Share

$$anonymous$$y pleasure. I'll just copy/paste first comment into original Q, so we can continue discussion if needed.

avatar image Abacab · Apr 20, 2015 at 09:15 PM 0
Share

@Glurth This still doesn't work. :( Can you spot the problem?

 void LateUpdate ()
         {
         
                 RaycastHit wallHit = new RaycastHit ();
                 Ray wallRay = new Ray (camera.transform.position, car.transform.position - camera.transform.position);
         
                 if (Physics.Raycast (wallRay, out wallHit, distance)) {
                         if (wallHit.collider.tag == "Wall") {
                                 flag = true;
                         } else {
                                 flag = false;
                         }
                 }
 
                 if (flag == true) {
                         camera.transform.position = wallHit.point;
                 }
         
         }
avatar image Glurth · Apr 20, 2015 at 11:06 PM 1
Share

This logic doesn't seem to actually do anything different.

True, you are using a flag now to hold the boolean hit-result, but you are still updating the position every Fixed update that the camera is touching the wall.

Try na$$anonymous$$g your flag "hadContactLastUpdateFlag". That descriptive name should you help you figure out how to setup the logic. (you are CLOSE)

avatar image Abacab · Apr 21, 2015 at 09:17 PM 0
Share

@Glurth I might need one more hint to figure it out. I am ashamed to admit it. :(

avatar image Glurth · Apr 21, 2015 at 10:29 PM 1
Share

Well, if you want to move the camera when it hadContactLastUpdate, you'll need to check the flag and take action BEFORE you update the flag for contact during your CURRENT update. Edit: keep in $$anonymous$$d though, you want to move it only if you have contact this update, and did NOT have contact last update.

avatar image Abacab · Apr 22, 2015 at 07:43 AM 0
Share

@Glurth This camera goes through the wall. :( By the way this is the last major thing that my game technically needs before release, so I am really appreciating your help.

 void LateUpdate ()
         {
                 RaycastHit wallHit = new RaycastHit ();
                 Ray wallRay = new Ray (camera.transform.position, car.transform.position - camera.transform.position);
         
                 if (Physics.Raycast (wallRay, out wallHit, distance)) {
                         if (wallHit.collider.tag == "Wall") {
                                 if (hadContactLastUpdateFlag == false) {
                                         hadContactLastUpdateFlag = true;
                                         camera.transform.position = wallHit.point;
                                 }
                         }
                         if (wallHit.collider.tag != "Wall") {
                                 hadContactLastUpdateFlag = false;
                         }
                 }
         }
avatar image Glurth · Apr 22, 2015 at 08:50 AM 1
Share

Oh, I guess you are setting the position elsewhere if your code also. I guess you could check a similar flag there too.

But I'm starting to think the other method I suggest may be easier; the results might be slightly different, but I suspect acceptable.

 Vector3 CarAtCameraHeight = camera.transform.position;
 CarAtCameraHeight.z=camera.transform.position.z;
 Ray wallRay = new Ray (camera.transform.position, CarAtCameraHeight - camera.transform.position);
      

You original logic would work, and I think this will prevent the sliding down (or up) effect.

P.S. I would love a copy of the game, please! You can contact me at my gmail address (same username).

avatar image Abacab · Apr 22, 2015 at 05:22 PM 0
Share

@Glurth I think my walls are just high enough so that CarAtCameraHeight is too high to make a collision. What can I do other than make the walls higher or the camera lower?

avatar image Glurth · Apr 23, 2015 at 12:36 AM 1
Share

Hmm, in this case, you probably WILL need to check a flag in the other place you set the camera position.

I guess you COULD get the Z position of the Wall itself, and use something like CarAtWallHeight, and CameraAtWallHeight in the raycast. This would prevent it from going over (or under) even the shortest wall.

I think my walls are just high enough so that CarAtCameraHeight is too high to make a collision.

This is a pure design choice question, rather than a program$$anonymous$$g question, so there is no right or wrong answer, but: Why not just let it pass over the wall? It would seem odd to me if the camera, following a car, just stopped short in the middle of the air.

avatar image Abacab · Apr 23, 2015 at 08:35 AM 0
Share

@Glurth The problem arises when the car makes a sharp turn behind a wall. This is my whole LateUpdate(), so while the camera might always go over walls, it might sometimes lose sight of the car. That is when I want the camera.transform.position = wallHit.point; to kick in.

 void LateUpdate ()
         {
                 float wantedAngle = rotationVector.y;
                 float wantedHeight = car.position.y + height;
                 float myAngle = transform.eulerAngles.y;
                 float myHeight = transform.position.y;
         
                 myAngle = $$anonymous$$athf.LerpAngle (myAngle, wantedAngle, rotationDamping * Time.deltaTime);
                 myHeight = $$anonymous$$athf.Lerp (myHeight, wantedHeight, heightDamping * Time.deltaTime);
         
                 Quaternion currentRotation = Quaternion.Euler (0, myAngle, 0);
                 transform.position = car.position;
                 transform.position -= currentRotation * Vector3.forward * distance;
                 Vector3 temp = transform.position; //temporary variable so Unity doesn't complain
                 temp.y = myHeight;
                 transform.position = temp;
                 transform.LookAt (car);
 
                 RaycastHit wallHit = new RaycastHit ();
                 Ray wallRay = new Ray (camera.transform.position, car.transform.position - camera.transform.position);
         
                 if (Physics.Raycast (wallRay, out wallHit, distance)) {
                         if (wallHit.collider.tag == "Wall") {
                                 if (hadContactLastUpdateFlag == false) {
                                         hadContactLastUpdateFlag = true;
                                         camera.transform.position = wallHit.point;
                                 }
                         }
                         if (wallHit.collider.tag != "Wall") {
                                 hadContactLastUpdateFlag = false;
                         }
                 }
         }
avatar image Abacab · Apr 28, 2015 at 08:12 AM 0
Share

@Glurth have you got any ideas?

avatar image Glurth · Apr 28, 2015 at 06:26 PM 1
Share

Try checking that flag in the other places you adjust the position too?

like here:

 transform.position = car.position;
 transform.position -= currentRotation * Vector3.forward * distance;
            
avatar image Abacab · Apr 29, 2015 at 05:28 PM 0
Share

@Glurth

This makes the camera switch very fast between being ABSOLUTELY THE WAY I WANT IT TO BE and the original being-behind-the wall state it was in. (And I know why, but I don't know how to fix it. :()

 void LateUpdate() {
     
         RaycastHit wallHit = new RaycastHit ();
         Ray wallRay = new Ray (camera.transform.position, car.transform.position - camera.transform.position);
         
                 if (Physics.Raycast (wallRay, out wallHit, distance)) {
                         if (wallHit.collider.tag == "Wall") {
                                 hadContactLastUpdateFlag = true;
                         } else {
                                 hadContactLastUpdateFlag = false;
                         }
                 }
 
                 if (hadContactLastUpdateFlag == true) {
                         camera.transform.position = wallHit.point;
                 } else {
                         transform.position = car.position;
                         transform.position -= currentRotation * Vector3.forward * distance;
                 }
    }
avatar image Glurth · Apr 29, 2015 at 05:40 PM 1
Share

I think you just need to use one more flag..wich I do below. This can actually be done (and optimized a bit) without needing another variable, can you see how?

 void LateUpdate() {
  
      RaycastHit wallHit = new RaycastHit ();
                      Ray wallRay = new Ray (camera.transform.position, car.transform.position - camera.transform.position);
              
                      if (Physics.Raycast (wallRay, out wallHit, distance)) {
                              if (wallHit.collider.tag == "Wall") {
                                      hadContactThisUpdateFlag = true;
                              } else {
                                      hadContactThisUpdateFlag = false;
                              }
                      }
      
                      if (hadContactThisUpdateFlag == true) {
                             if(hadContactLastUpdateFlag == false)
                             {
                                 camera.transform.position = wallHit.point;
                             }
                             else
                             {
                                 //camera is rubbing against wall- contact last turn AND this turn- dont move camera
                             }
 
                      } else {
                              transform.position = car.position;
                              transform.position -= currentRotation * Vector3.forward * distance;
                      
                      }
                     hadContactLastUpdateFlag=hadContactThisUpdateFlag;
  }

avatar image Abacab · Apr 29, 2015 at 05:48 PM 0
Share

@Glurth I honestly know what I should do in that else with the comment, but I can't put it into code. I don't know how I should store that wallHit.point so that I can keep the camera in the same position.

You have been extremely helpful and I really owe you a big one.

This just generates an error "Use of unassigned local variable 'tempWallCamera'

 if (hadContactThisUpdateFlag == true) {
                         Vector3 tempWallCamera;
                         if (hadContactLastUpdateFlag == false) {
                                 camera.transform.position = wallHit.point;
                                 tempWallCamera = wallHit.point;
                         } else {
                                 camera.transform.position = tempWallCamera;
                         }
avatar image Glurth · Apr 29, 2015 at 06:12 PM 1
Share

If that is the effect you want, just leave it blank: assu$$anonymous$$g you don't set the camera position anywhere else in your code, it will retain the last value you assigned.

You are getting that error because of where you are declaring tempWallCamera. It will go out-of-scope, and loose it's assigned value, when the LateUpdate function exits. Also, it will be re-declared each time the function is called. You would need to make it a member of your class and declare it as such in order for it to stay-in-scope when LateUpdate exits. Do some research on "scope" for more details (Important program$$anonymous$$g concept).

You have been extremely helpful and I really owe you a big one.

You still haven't promised me a copy of the game ;)
avatar image Abacab · Apr 29, 2015 at 06:16 PM 0
Share

@Glurth It is still changing between being behind the wall and being in the right position (just above the car when reversed all the so that the rear bumper hits the wall).

And it is changing very very fast between those two states.

And yes you are due a copy of my game once it is 100% completed, however that is not a huge reward since I am planning to have it free for download in the App Store.

Any idea what might make the camera switch between the two states?

avatar image Glurth · Apr 29, 2015 at 10:20 PM 1
Share

Hmm, I THIN$$anonymous$$ what might be happening is after you set the camera position to hit-point, the next update cycle, it is no longer detecting a hit? So the next update, hadContactLastUpdateFlag will be false. for some reason I was thinking the camera was supposed to be on the far side of the wall. This should be a bit simpler...

     RaycastHit wallHit = new RaycastHit ();
     Vector3 testCameraPos = car.position;
     testCameraPos -= currentRotation * Vector3.forward * distance;
     Ray wallRay = new Ray (testCameraPos, car.transform.position - testCameraPos);
               
     if (Physics.Raycast (wallRay, out wallHit, distance)) {
             if (wallHit.collider.tag == "Wall") {
                     camera.transform.position = wallHit.point;
             } else {
                     camera.transform.position = testCameraPos;
             }
     }


*notice that the hit-point computation does NOT use the camera's current position, so I dont thin it will slide.

avatar image Abacab · Apr 29, 2015 at 10:43 PM 0
Share

@Glurth It almost works!

First: The camera doesn't follow the car anymore

Second: I reverse towards the wall and the car almost hits the camera (doesn't the wall yet) and the camera jumps backwards. Then the car hits the wall and the camera is where I'd want it to be.

Any idea (did you understand)?

avatar image Glurth · Apr 30, 2015 at 09:12 AM 1
Share

well I did change one line from

 transform.position=

to

 camera.transform.position=

I'm no sure how/where camera is defined, so maybe this was wrong?

avatar image Abacab · Apr 30, 2015 at 10:23 AM 0
Share

It is now working with this!!!

 RaycastHit wallHit = new RaycastHit ();
 Vector3 testCameraPos = car.position;
 testCameraPos -= currentRotation * Vector3.forward * distance;
 Ray wallRay = new Ray (testCameraPos, car.transform.position - testCameraPos);
         
                 if (Physics.Raycast (wallRay, out wallHit, distance)) {
                         if (wallHit.collider.tag == "Wall") {
                                 transform.position = wallHit.point;
                         } else {
                                 transform.position = testCameraPos;
                         }
                 } else {
                         transform.position = car.position;
                         transform.position -= currentRotation * Vector3.forward * distance;
                 }
avatar image Glurth · Apr 30, 2015 at 08:59 PM 0
Share

great! lemme know when you publish it, and what it's called, ill try it out.

avatar image Abacab · May 03, 2015 at 05:56 PM 0
Share

I sure will!

0 Replies

  • Sort: 

Welcome to Unity Answers

If you’re new to Unity Answers, please check our User Guide to help you navigate through our website and refer to our FAQ for more information.

Before posting, make sure to check out our Knowledge Base for commonly asked Unity questions.

Check our Moderator Guidelines if you’re a new moderator and want to work together in an effort to improve Unity Answers and support our users.

Follow this Question

Answers Answers and Comments

19 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

Related Questions

Raycast hitting objects to the left of my player 1 Answer

Why in Unity3D RaycastHit. textureCoord always return 0,0 after building the project? 1 Answer

On raycast hover change crosshair image 1 Answer

How can I change this script? 0 Answers

Mouse pos + raycast 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