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 Troas · Aug 09, 2014 at 08:11 PM · scenegamenewbie

Make ray follow mouse position from player origin (Isometric)

I'm trying to get a firing mechanic working in my isometric game. I want to be able to shoot along the x/z-axis but not have the ray go up or down the y-axis. Instead I want it "zero'd" out on the y-axis at all times.

Also the ray doesn't point precisely to the mouse position unless it is directly infront. As I veer left or right of the origin it keeps getting significantly less accurate at point at the mouse to the point it will be nearly 10 degrees off.

The white square denotes where the mouse cursor was. The print screen would not capture the mouse cursor for some reason.

alt text

alt text

alt text

     using UnityEngine;
     using System.Collections;
      
     public class Weapon : MonoBehaviour {
      
         public float fireRate = 0;
         public float damage = 10;
         public LayerMask notToHit;
      
         float timeToFire = 0;
         Transform firePoint;
      
         void Awake () {
             firePoint = transform.FindChild ("FirePoint");
             if (firePoint == null) {
                 Debug.LogError ("firePoint is null");    
             }
         }
     
         void Update () {
      
             Vector3 mousePostion = Camera.main.ScreenToWorldPoint (Input.mousePosition);
             mousePostion.y = 0;
             Vector3 firePointPosition = new Vector3 (firePoint.position.x, firePoint.position.y, firePoint.position.z);
        
             float distToMouse = Vector3.Distance(mousePostion, firePointPosition) ;
        
             RaycastHit hit;
             Ray myRay = new Ray (firePointPosition, mousePostion);
      
             Debug.DrawRay (firePointPosition, mousePostion);
      
             if (fireRate == 0) {
                 if (Input.GetButtonDown("Fire1") && Physics.Raycast(myRay, out hit, distToMouse, notToHit)) {
                     Shoot();
                 }
             }
        }
      
        void Shoot () {
             Debug.Log ("Fire!");
        }
 }

How do I make a ray that stays on the same Y-axis as the player, can follow the mouse's movement along the x/z-axis in the world with precision?

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

1 Reply

· Add your reply
  • Sort: 
avatar image
0

Answer by robertbu · Aug 10, 2014 at 02:53 AM

When a camera is at an angle to a surface, you cannot use ScreenToWorldPoint() to find that position. The solution is a Raycast(). You could Raycast() against the green block, but if the surface is flat, then there is a cheaper way. You can use Unity's mathematical Plane class. How to setup the code will depend on how you setup your object. In particular whether the green block surface is on the XZ plane or the XY plane. Let me assume the XZ plane. To find the position it is best to use the position of the player (or whatever object you are going to place). A bit of untested example code:

  Plane plane = new Plane(Vector3.up, player.position);
  Ray ray = Camera.main.ScreenPointToRay(Input.mousePosition);
  float dist;
  plane.Raycast(ray, out dist);
  Vector3 pos = ray.GetPoint(dist);

So pos is where you would move an object in world space so that it would be under the mouse position. Note this code assumes that the Raycast() cannot fail. If you allow the camera to look parallel to the green block or away from the green block, then you need to check the return value of the plane.Raycast() call.

Another solution is to use Collider.Raycast() to cast against the block (or against an invisible plane that passes through the player's pivot point).

Comment
Add comment · Show 10 · 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 Troas · Aug 10, 2014 at 03:39 PM 0
Share
 plane.Raycast(ray, out dist);
  Vector3 pos = ray.GetPoint(dist);

This is the only part that confuses me. Is the plane itself casting a ray? Or is the "ray" being cast through the mouse position from the camera intersecting the plane and that is what you are detecting with "plane.Raycast(Ray, out dist);"

Then the Vector3 pos is the point on the ray that the mouse lies when intersecting the plane?

So if I wanted to fire something to that point where the mouse lies would all I need to do is use the "ray.GetPoint(dist);" and fire the the object to the "Vector3 pos"?

$$anonymous$$aking sure I understand everything here.

I tried it though and ended up with this:

 Plane plane = new Plane (Vector3.up, transform.position);
         Ray rayTo$$anonymous$$ouse = Camera.main.ScreenPointToRay (Input.mousePosition);
         float dist;
         plane.Raycast (rayTo$$anonymous$$ouse, out dist);
         Vector3 targetPos = rayTo$$anonymous$$ouse.GetPoint (dist);
 
         Debug.DrawRay (transform.position, targetPos);

Ends up causing things like this:

http://i59.tinypic.com/2jv780.png

http://i57.tinypic.com/30t5h68.png

http://i58.tinypic.com/abnm2h.png

avatar image robertbu · Aug 10, 2014 at 04:33 PM 0
Share

A mouse moves on a 2D surface. Unity is 3D, so the world position of the mouse in 3D space will vary based on the distance the position is from the mouse/camera. A Raycast() of any sort (Physics.Raycast(), Collider.Raycast(), Plane.Raycast(), Physics2D.Raycast()), shoots at beam starting at some position going in some direction to see what/where something is hit.

So based on the perspective geometry, a ray is constructed (ScreenPointToRay()). A Ray has an origin and a direction. Plane.Raycast() takes the specified ray and casts it against the mathematical plane. It returns two pieces of information. The return value from the function is a boolean that says whether the ray hit anything. If the direction of the ray is parallel to the plane or away from the plane, then it will fail to hit the plane. The 'dist' is filled in by the function as well. Assu$$anonymous$$g the Plane.Raycast() succeeds, then 'dist' is the distance from the origin of the ray that the ray hit the plane. We can convert that distance into a world point by using Ray.GetPoint() and passing the distance from the origin. GetPoint() walks down the ray from the origin the specified distance to deter$$anonymous$$e a position.

Note given the geometry in the image, there is no way for the ray to miss the plane, so I did not check its return value. But I did indicate that if you allow the camera to look away, then you would need to check the return value to see if the plane was hit. Also this is a mathematical plane parallel to the XZ plane and passing through the pivot point of the 'character'.

avatar image robertbu · Aug 10, 2014 at 06:28 PM 0
Share

I missed your images with your comment above. Not sure why. Did you add them in an edit? Anyway, something is off. Just to make sure, your grey surface is on the XZ plane? If not, then is one source of the problem. Also I'm not sure of your na$$anonymous$$g which makes be consider I missed what you are trying to here. 'targetPos' should be the position directly under the mouse just above the grey surface (half the height of a cube if your cubes are resting on the grey surface). If you had an object and did:

  transform.position = targetPos;

...that that object should appear under the mouse cursor just above the grey surface.

avatar image Troas · Aug 10, 2014 at 07:18 PM 0
Share

Yes you are exactly right in your thinking and yes I did add them in an edit so here are the direct links.

  1. http://i58.tinypic.com/abnm2h.png

  2. http://i59.tinypic.com/2jv780.png

  3. http://i57.tinypic.com/30t5h68.png

The ray can now go 360 deg around the player so that problem is solved. The plane is 0'd on the X/Z so that is not the issue. The issue is it seems to not get where the mouse precisely is but it does accurately follow its movement.

It is almost as if it is "offset" by a certain amount. I thought centering the camera on the player would help but maybe I did that wrong. Could it also be because the camera is a child of the player yet is not at the "0,0,0" position? The camera's transform is currently (0,0,-15) because that was the only way I could center it on the player, I do not know how else to do it.

avatar image robertbu · Aug 10, 2014 at 08:12 PM 0
Share

The issue is likely where you are placing the plane for your plane.Raycast(). Here is a diagram. It is not an accurate representation of your current geometry, but only serves to illustrate how plane placement impacts the final position.

alt text

Image this is cut-away side view of your grey plane with a blue block (for scale) placed on the plane. Imagine that your plane is centered at Vector3.zero. The large arrow is the view onto the plane. The small green arrow is the raycast. The black and red lines represent three different placements of the plane used in the Plane.Raycast(). And the black dots represent the raycast hit for each of the possible planes. The bottom plane uses Vector3.zero as its position. The middle one uses transform.position of the block and the upper one is the top of the block...something like:

  var pos = block.position + Vector3.up * 0.5 * blockHeight;

As you can see, which plane used impacts the position of the hit point as view by the user. So you need to pick the point for your plane (second parameter) that works for your geometry. I'd assumed you were looking for the calculation to position a player on the plane when I suggested player.position, but Vector3.zero may be what you are looking for.

exampleraycast.png (14.1 kB)
Show more comments

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

Skybox does not show up in Scene mode... 6 Answers

[Solved]Game Objects Visible in Game tab but not on Scene tab 3 Answers

Problem stopwatch start the game. 1 Answer

unity: scene shows nothing, PLEASE HELP 1 Answer

Why is half of my "game" tab completely grayed out? 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