Sign in to follow this  
VanillaSnake21

Unity [C#] Getting ray from mouse position

Recommended Posts

I'm trying to build a small game in Unity and I ran into this problem. I want to use an unlocked cursor in the game meaning that the look at vector of the camera would not exactly point to the cursor. This is the default setting in Unity it's done by not locking the cursor the center of the screen and simply using the offset, instead the camera moves by the distance that the user moved the cursor. This allows me to use a hardware cursor in the game and also I kind of like the feel of it since the game I have in mind involves a lot of 3D picking. So the problem is that when I try to actually shoot a ray from camera through the cursor (converted to 3D position) the shooting vector is off by a lot at certain camera angles and very close to what it's supposed to be at other angles. I'm not sure what's causing it, this is the code I have so far (except from a Unity C# script)
[code]
vector3 v = Camera.ScreenPointToRay(mousePos)
ray = v.direction;
[/code]

I'm not exactly sure how to fix this or even why it's happening. I suspect that the conversion of the 2D cursor to 3D space results in a false Z value in some camera orientation but I don't exactly how to fix it. Any help appreciated

Share this post


Link to post
Share on other sites
From the documentation, ScreenPointToRay takes a screen position in pixels. Are-you sure that your mousePos is in pixels? It's not clear from your post what the 2D to 3D converstion your talking about exactly is. As far as I know, you shouldn't have any 2D to 3D conversion to do.

Share this post


Link to post
Share on other sites
[quote name='Faelenor' timestamp='1353071694' post='5001529']
From the documentation, ScreenPointToRay takes a screen position in pixels. Are-you sure that your mousePos is in pixels? It's not clear from your post what the 2D to 3D converstion your talking about exactly is. As far as I know, you shouldn't have any 2D to 3D conversion to do.
[/quote]

I meant converting a 2D cursor postion to 3D world space, at least that's what I thought I had to do. I just noticed the doc says that z coordinate is ignored, but then how does it build a ray if the z is ignored? And yes the mousepos is in pixels just checked the doc Input.mousePosition. I hope that I stated my original problem clearly. I basically want to use the actual distance that the mouse moved instead of the deltaX deltaY to control the camera view. So you could still move the cursor normally and it would feel like a normal cursor rather then crosshairs in an fps.

Share this post


Link to post
Share on other sites
Well, a ray is defined by two things: its start position and a direction. The start position is the camera position and the direction is what is returned by ScreenPointToRay. The z component of the mouse position is useless, because the direction will be the same for any point in space that appears to be at that pixel position. I don't know if I'm clear enough. Think of it as a wire starting from the camera and going away to infinity. Any point on this wire has the same pixel position but different z values. That means that we can ignore the z value to get the ray direction.

Share this post


Link to post
Share on other sites
[quote name='Faelenor' timestamp='1353090642' post='5001595']
Well, a ray is defined by two things: its start position and a direction. The start position is the camera position and the direction is what is returned by ScreenPointToRay. The z component of the mouse position is useless, because the direction will be the same for any point in space that appears to be at that pixel position. I don't know if I'm clear enough. Think of it as a wire starting from the camera and going away to infinity. Any point on this wire has the same pixel position but different z values. That means that we can ignore the z value to get the ray direction.
[/quote]

You made an example of a wire going from the camera to infinity, and I'm assuming the camera's lookAt vector 'z' is used to make the 3D ray that points in that direction but also has all the 3D points that that pixel contains because as you said it remains constant. But isn't that assuming that the camera lookAt vector is pointing at the object on which you clicked? Please correct if I'm wrong because I very well could be. But assuming that's so, in this camera model I'm trying my pointer doesn't point to the same place the character is looking at because by the time I drag the cursor from left to right of the screen, the game character would have made a few turns around the up axis. This way the cursor ends up in random places like being at the very bottom of the screen when the character is looking directly up or could be in upper left of the screen when he's facing directly forward. Assuming all of this how then can I get the actual direction point I'm clicking on? Again correct me if I said anything off, I'm just starting trying to understand raycasting and picking as I'm going through this book. Edited by VanillaSnake21

Share this post


Link to post
Share on other sites
The look at direction of the camera is the ray direction for the center of the screen only, for the other pixels, you need to call ScreenPointToRay. I'm really not sure I understand what you mean, so please try to explain what you're trying to do with more details or post some code.

By the way, your initial example is wrong, the ScreenPointToRay method returns a Ray, not a vector. Did you really use this code?

Share this post


Link to post
Share on other sites
[quote name='Faelenor' timestamp='1353350922' post='5002408']
The look at direction of the camera is the ray direction for the center of the screen only, for the other pixels, you need to call ScreenPointToRay. I'm really not sure I understand what you mean, so please try to explain what you're trying to do with more details or post some code.

By the way, your initial example is wrong, the ScreenPointToRay method returns a Ray, not a vector. Did you really use this code?
[/quote]

I've been using ScreeinPointToRay and it doesn't work. The ray that I get doesn't go from camera to the object I hit. I don't know how else to explain it. Imagine a character facing directly forward, in most games that would also mean that the cursor or crosshairs are also directly in the middle of the screen. I could have my cursor be located at ANY point on the screen while the character is still facing forward. So lets say I click the mouse button while pointing at a rock on the ground (rember the character is facing forward so the rock is at the lower right corner of the screen). How would I get a ray that goes from camera to rock?

Share this post


Link to post
Share on other sites
ScreenPointToRay does exactly that: compute a ray for any pixel position on screen. Of course this works for any position on screen and not only for a centered crosshair, otherwise the function wouldn't take any parameter! If it doesn't work, it means you're not using it correctly and that's why I asked you to post some code. Edited by Faelenor

Share this post


Link to post
Share on other sites
I guess I should have posted code earlier but I wanted to see if I could understand what's going on first, it would be pretty embarassing if I've been using this simple function in the wrong way all this time... Allright so here's the main code, it's attached to my Player character:

[source lang="csharp"]
//Activates when user presses a left mouse button
if(Input.GetButtonUp ("Fire1"))
{
Rigidbody bulletInst = Instantiate(bullet, transform.position, transform.rotation) as Rigidbody;
Ray camToCursorRay = Camera.main.ScreenPointToRay(Input.mousePosition);
shotDirection = camToCursorRay.direction; //public global float used to monitor this var
bulletInst.AddForce(shotDirection * shotPower); //shotPower multiplier set to 1500f


}[/source]

Share this post


Link to post
Share on other sites
What's transform.position? If it's not the camera position or ray origin, then the direction won't point to where you clicked. And by the way, I think it would be better to give an impulse to your bullet by setting its velocity directly instead of using AddForce.

Share this post


Link to post
Share on other sites
[quote name='Faelenor' timestamp='1353438714' post='5002727']
What's transform.position? If it's not the camera position or ray origin, then the direction won't point to where you clicked. And by the way, I think it would be better to give an impulse to your bullet by setting its velocity directly instead of using AddForce.
[/quote]

The script is attached to the Player character so it's the center of the player capsule. While it's not the camera transfrom, camera is also attached to this player and it's position is maybe 0.1 units up in y direction from player capsule, but let me try to set it to camera explicitly.

Edit: Yes that was it! The ball flies in the right direction, and I'll look into setting the impulse, thanks Faelnor! Edited by VanillaSnake21

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this  

  • Forum Statistics

    • Total Topics
      628277
    • Total Posts
      2981770
  • Similar Content

    • By ForgedInteractive


      Who We Are
      We are Forged Interactive, a small team of like-minded game developers with the sole purpose of making games we love! We're a team of artists, animators, programmers, level designers, writers, composers, producers, and other creative minds. We want to make games that you, the modern gamer want to play! We hope to build a community that enjoys our games as much as we love creating them. With your feedback and support we will be able to achieve that.

      About the Game
      GAME NAME is a fun, action-packed army builder with unique characters, challenges and engaging levels. Set forth on an adventure to protect friends, family and countrymen from new adversaries. Once defeated your enemies turn coat and join you in your adventures. Players can enjoy a range of troops and abilities based on their gameplay style which become more important as maps introduce more challenging terrain, enemies and bosses. Strong orc knights, dangerous shamans, and even a dragon are out on the prowl. Knowing when to fight and when to run, and how to manage your army is essential. Your actions alone decide the fate of this world.

      Previous Work by Team
      Although we are working towards our first game as a team, our team members themselves have past experience in the industry.
      This includes members who have worked on titles including:
      Final Fantasy Kingsglaive, FIFA, Xcom 2 and Civilization.

      Who are we looking for? 3D Modellers Concept Artists Marketing Specialists Level Designer

      What do we expect? Reference work or portfolio. Examples what have you already done and what projects you have worked on academic or otherwise. The ability to commit to the project on a regular basis. If you are going on a two-week trip, we don't mind, but it would be good if you could commit 10+ hours to the project each week. Willingness to work with a royalty based compensation model, you will be paid when the game launches. Openness to learning new tools and techniques
      What can we offer? Continuous support and availability from our side. You have the ability to give design input, and creative say in the development of the game. Shown in credits on websites, in-game and more. Insight and contacts from within the Industry.
      Contact
      If you are interested in knowing more or joining. Please email or PM us on Skype. Myself or Colin will reply to you within 48 hours.

      E-mail: Recruitment@ForgedInteractive.com
      Skype: ForgedInteractive

      Regards,
      David and Colin

      Follow us on:

      Facebook: https://www.facebook.com/ForgedInteractive/
      Twitter: @ForgedInteract
      Youtube: https://www.youtube.com/channel/UCpK..._as=subscriber
      Reddit: https://www.reddit.com/user/Forged_Interactive/
    • By Eck
      I just saw their courses were knocked down to $10 each and figured I'd share the info here. They have stuff for Unity, Unreal, drawing, business, etc. I haven't used their stuff before, but the previews I looked at seemed pretty good and there is a user review system as well.
      https://www.udemy.com/courses/search/?q=Unity&src=ukw
      - Eck
       
    • By zizulot
      first and only logo , for now
    • By sidbhati32
      I am working on a game in which we control a rectangular box at the bottom of the screen. Three sphere which has alphabets in it fall down. When the game starts, a word is generated from the predefined list of words(which I'll give) and we are supposed to touch the correct sphere having the alphabet based on that word. The question is how to detect if I have touched the correct sphere. 
      secondly, if I have touched a correct sphere before and there is no recurrence of that alphabet in that word then during the second wave the game should not proceed if I touch the same alphabet again.
      Looking forward to your answers, i have to submit this project in a couple of days. please help! (Working on Unity 3D)
      Thanks
    • By NDraskovic
      Hey guys,   As the title says, I'm trying to control a desktop game by using my mobile phone as a controller.  I created two scenes, one that acts as a server, other as a client.    Server has this code: void Start () {         Test = "Nothing yet happened";         NetworkServer.Listen(25000);         NetworkServer.RegisterHandler(888, ServerReceiveMessage);     }         private void ServerReceiveMessage(NetworkMessage message)     {                 StringMessage msg = new StringMessage();         msg.value = message.ReadMessage<StringMessage>().value;         if (!String.IsNullOrEmpty(msg.value))         {             Test = "Message received";             string[] deltas = msg.value.Split('|');             Horizontal = Convert.ToSingle(deltas[0]);             Vertical = Convert.ToSingle(deltas[1]);             TestScript.MoveForward(Vertical);             TestScript.RotateAroundY(Horizontal);         }         else         {             Test = "Nothing received";         }     }  
        And client this:  private void Connect()     {              client.Connect(IPAddress, 25000);           }     void Start () {         client = new NetworkClient();         Connect();            }         void Update () {    #if UNITY_ANDROID         MobileTouches = Input.touches;         if (MobileTouches.Length > 0)         {             for (int i = 0; i < MobileTouches.Length; i++)             {                 if (MobileTouches[i].phase == TouchPhase.Moved)                 {                     Horizontal = MobileTouches[i].deltaPosition.x;                     Vertical = MobileTouches[i].deltaPosition.y;                 }else if(MobileTouches[i].phase == TouchPhase.Stationary)                 {                     Connect();                                  }             }         } #elif UNITY_EDITOR               Horizontal = Input.GetAxis("Horizontal");         Vertical = Input.GetAxis("Vertical"); #endif         thumb.Translate(Vector3.up * Vertical * Time.deltaTime);         thumb.Translate(Vector3.right * Horizontal * Time.deltaTime);         SendControllerInfo();     }     static public void SendControllerInfo()     {         if (client.isConnected)         {             StringMessage msg = new StringMessage();             msg.value = Horizontal + "|" + Vertical;             client.Send(888, msg);         }     }  
        Ip address is hard coded, I just replaced it with the "IpAddress" variable. The code itself builds fine, and when I try to run in on a desktop computer, it works as expected (just a simple movement of an object on the server screen). However when I try to publish the client scene to a mobile device (Android), it doesn't connect to the server. They are both connected to the same network. Can anyone tell me what the problem might be?   Thanks
  • Popular Now