Wayback Machinekoobas.hobune.stream
May JUN Jul
Previous capture 14 Next capture
2021 2022 2023
2 captures
13 Jun 22 - 14 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 empire2202 · Sep 13, 2013 at 08:50 PM · 3drotate objectscreentoworldpointtargetinglookatmouse

weapon aiming in 3d space using the (2d) mouse

This question is very hard to explain, as seen in my previous question http://answers.unity3d.com/questions/535643/rotate-the-player-to-face-where-the-mouse-is-point.html so bear with me.

Basically I have a 3d, 3rd person game set in space where the use controls a spaceship. To control the rotation of the ship the user moves the mouse using the following script:

 var lookFactor = 100; //This amount indicates how far away the ship and weapons are aiming
 function Update () 
     { 
     var distance = (transform.position.z - Camera.main.transform.position.z)*lookFactor;
     var position = Vector3(Input.mousePosition.x, Input.mousePosition.y, distance);
     position = Camera.main.ScreenToWorldPoint(position);
     transform.LookAt(position);
     }

This code works quite well as a mouse look code but at the moment here's how my weapons function: When the player clicks the left mouse button a missile prefab is instantiated directly infront of the ship with the same rotation as the ship then force is applied to its rigid body to propel it forward. But I'm trying to change this so that when the player clicks the left mouse button, a missile prefab is instantiated infront of the ship facing the mouse (instead of sharing the ships rotation). Except in 3d space using the ScreenToWorldPoint I give the mouse a fixed z co-ordinate, this is no good performing weapon aiming in 3d space. I need a way of changing the 'fixed' z co-ordinate to match that of the object the mouse is pointing at but never exceeding the max range of the selected weapon (hope that made sense). I'll give an example:

The players ship has two beam cannon turrets (one on each wing) which can rotate independently from the ship. These turrets follow the mouse (with it's annoyingly fixed z co-ordinate ;D). Lets say the player wants to shoot at a ship that's 250m away, but the z co-ordinate is fixed at 1000m, even though the player places the cursor directly on the ship, there is a chance that 1 or even both lasers will miss because they're aiming far behind the target ship. This, I'm sure you realise is not what is wanted, I need to know if there's a way (and what it is) to change the z co-ordinate of the mouse depending on what it's pointing at (wow, hope that made sense) I also need the z co-ordinate of the mouse to change appropriately if the player aims near a ship (because they could be accounting for movement and aiming infront of the ship might hit it (if the z co-ordinate is changed properly))

like I said, to me this is very hard to explain, if you need anything clarified please just ask, also refer to the question linked at the top for (a little bit) more information. This problem has had me stuck for weeks and this question took me like 30 mins to write, trying to make it as clear as possible. Thanks in advance.

If you still don't quite understand what I'm aiming for, look at a game like Star Conflict, I need an aiming system like that, but I just can't think of how to change the z correctly, especially if the player is aiming not even at but near the ship to account for movement D:

EDIT: here's what I'm thinking so far (this is just a concept, no code at the moment):

when the mouse is over an object, we compare the objects z position to the camera's z position, the difference becomes the z position of the mouse, is this possible? and would it work? and all objects could have an invisible sphere attached to them which counts as part of the object in terms of comparing z position (for if they aim not directly at the ship)

Comment
Add comment · Show 15
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 ShadoX · Sep 13, 2013 at 10:53 PM 0
Share

I'm assu$$anonymous$$g that the game displays something like this...

alt text

(sorry for my poor illustration)

or perhaps more like ...

alt text

Trailer @ http://www.youtube.com/watch?v=X-wmo4$$anonymous$$5-ls

In which case - can't you just cast a ray from the ship towards the enemy (clicked position) to deter$$anonymous$$e the angle of the missile?

As for ai$$anonymous$$g near a enemy, you could try placing a temporary, invisible plane (or sphere around the enemy) (that is facing the camera and positioned at the enemies position) to have the ray hit this "invisible object" and be fired into that direction, but in this case you would still have to figure out which enemy is closer to the mouse cursor (in 2D space) to chose which enemy to use that invisible wall on.

I'm guessing that the missiles would still miss, but they would at last fly in that direction. Unfortunately this doesn't really sound like a pretty solution, but I wanted to mention it anyway.

[edit] Or you could actually just display the 3D game while running a little 2D simulation (not sure if this is the correct term) in the background. Basically playing a 2D game while displaying the 3D version. Checking the coordinates in 2D (x,y or y,x I guess) would probably be a lot easier than 3D.

avatar image empire2202 · Sep 14, 2013 at 07:14 AM 0
Share

your top image isnt displaying, but yeah sort of. note: I know javascript but am somewhat new to unity(script), although I'm sure your input would normally help someone who knows how to use all the unity functions, I don't. For your answers to be truly helpful please include adleast a small amount of sample code

avatar image Benproductions1 · Sep 14, 2013 at 09:43 AM 0
Share

@empire2202, @ShadoX said to use "raycasts", so why not just look it up? It's not work posting code because it's been done so many times before. On very, very similar questions

avatar image ShadoX · Sep 15, 2013 at 02:58 PM 0
Share

@empire2202 Sorry, not sure why the image isn't working. Seems fine to me. As for the code - I do post code sometimes, but I'd have to post everything. I rather enjoy seeing people figure things out by themselves than giving them code (since that's pretty much what program$$anonymous$$g is about).

I'll try to post some example project/scene a bit later as I'm a bit busy right now.

avatar image empire2202 · Sep 15, 2013 at 05:37 PM 0
Share

I understand what raycasting is and, with the help of google I know how to use it, but I'm not sure how to apply it to this problem. As far as I can tell you're suggesting casting a ray from the play ship in the direction of the mouse, but that won't help, I might aswell have just fired my weapon. The problem is that the mouse operates in 2d space, but to accurately aim and fire at a distant ship, we have to give it an accurate z position, the problem is getting and setting that z value. I am not looking for some sort of auto-aim system where the player clicks on or near a ship and it always hits, I'm just looking for a way to give the mouse an accurate enough z position that, with ti$$anonymous$$g, ai$$anonymous$$g and estimation, the player could hit a moving target. With my current system where the mouse is treated as being 10 units away from the ship, unless the enemy is 10 units away, the ai$$anonymous$$g is inaccurate and I can't hit because, by the time the projectile goes x distance (where x is the distance from the player to the enemy), it is nowhere near where the mouse was.

Show more comments

1 Reply

· Add your reply
  • Sort: 
avatar image
0

Answer by empire2202 · Sep 18, 2013 at 05:33 PM

I've got it to work! But I've been told that OnMouseOver only logs the most forward object, so if anyone can suggest a modification to my code to allow the detection of multiple potential targets so my code can select the highest priority target. Here is code I attach to objects so they can be targeted: static var mouseOver = null; static var mouseOverDist : float; static var mouseOverPriority : int = 0; var self = gameObject; var selfPriority = 2;

 function Start () {
     if(self.tag == "aimingSphere"){
         selfPriority = 1;
     }
     else selfPriority = 2;
     
     Debug.Log("Self Priority is" + selfPriority + "because self is" + gameObject);
 }
 
 function setMouseOver () {
     mouseOver = self;
     mouseOverPriority = selfPriority;
     mouseOverDist = transform.position.z;
     Debug.Log("Mouse is now over " + gameObject);
 }
     
 function OnMouseOver () {
     if(mouseOver == null){
         setMouseOver ();
     }
     else if(self == SpaceShip.Target) {
         setMouseOver ();
     }
     else if(mouseOverPriority < selfPriority) {
         setMouseOver ();
     }
     //else if((mouseOverPriority == selfPriority) && ((self.z - Player.z) < (mouseOver.z - SpaceShip.Player.z) {
     //    setMouseOver ();
     //}
 }
 
 function OnMouseExit (){
     mouseOver = null;
     mouseOverPriority = 0;
     
     Debug.Log("Mouse is no longer over " + gameObject);
 }

and this is the code I use to shoot:

 var bulletTest : Transform;
 
 var cam : Transform;
 
 public static var test = [0, 2, 15, 2, 1, 1, 1000];
 
 var names = [];
 
 var bulletArray = [bulletTest];
 
 public static var weapons = [test];
 //<id>, <range>, <damage>, <shots>, <cooldown(1)/overheat(0)>, <time>, <prefabBullet>
 
 var shootForce = 1000;
 
 public var id = 0;
 public var range = 1;
 public var damage = 2;
 public var shots = 3;
 public var cooldown = 4;
 public var coolTime = 5;
 public var force = 6;
 //These variables are just to make it easier for me when I want to access stats of weapons
 
 public static var equippedWeapon = 0;
 public static var lastShot : float;
 public static var lastShotInt : int;
 public static var lastWeapon : int;
 public static var cooltime : float;
 public static var lastWeaponShot : int;
 var distanceFromShip = 15;
 private var hitdist : float = 30;
 
 public static var weaponCooldown;
 public static var currentBullet : Transform;
 
 var ray = null;
 var targetPoint = null;
 var targetRotation = null;
 
 function Start () {
 }
 
 function Update () {
     lastShot += Time.deltaTime;
     weaponCooldown = weapons[equippedWeapon][cooldown];
     hitdist = mouseOver.mouseOverDist - cam.position.z;
     Shoot ();
 }
 
 function Shoot () {
     if(Input.GetButton("Fire1")) {
         if(weapons[equippedWeapon][cooldown])
         {
             if(lastShot > weaponCooldown)
             {
                 ray = Camera.main.ScreenPointToRay (Input.mousePosition);
                 targetPoint = ray.GetPoint(hitdist);
                 targetRotation = Quaternion.LookRotation(targetPoint - transform.position);
                 lastShot = 0.0;
                 var equippedId = test[0];
                 lastWeaponShot = weapons[equippedWeapon][id];
                 var instanceLaser = Instantiate(bulletArray[equippedId], transform.position + transform.forward*distanceFromShip, targetRotation);
                 instanceLaser.rigidbody.AddForce(instanceLaser.forward * weapons[equippedWeapon][force]);
             }
         }
     }
 }

The parts where the solution is (for those interested) in the update function and the shoot function, the 1st code just detects which object the player is looking at. But again this system only detects the front most object, if anyone cane supply an alternate detection method that can, please tell me. Thanks for all your help.

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 empire2202 · Sep 24, 2013 at 12:12 PM 0
Share

To make this code detect objects placed behind others, should I cast an array from the camera.x, camera.y, and player.z into the world in a straight line then log and compare all the objects it hits and decide which is the highest priority target (the most likely the user is actually trying to shoot at)?

If so can someone please supply a link or an answer that is a small tutorial/explanation as to how I would do this. thanks.

avatar image empire2202 · Oct 17, 2013 at 05:04 PM 0
Share

@ArkaneX how do I make a raycast log all the objects it hits? I've finally gotten round to program$$anonymous$$g this new system using raycasting but I tried to detect which object that it hit that is most likely for the player to be ai$$anonymous$$g at by comparing hit[x] to other things but I get the error type object doesn't support slicing. I know this means that it stores it's hit as an object not an array, which means it can only store one hit (correct me if I'm wrong). How can I make it so it stores everything hit?

avatar image ArkaneX · Oct 17, 2013 at 05:27 PM 0
Share

You can use Physics.RaycastAll. Additionally, it's worth mentioning that both Raycast and RaycastAll can be used with layermask parameter. You can use this parameter to force raycast to ignore objects belonging to specific layer(s).

avatar image empire2202 · Oct 17, 2013 at 05:35 PM 0
Share

wow fast response, thanks for help, I didn't know there was a whole different thing for this, I'll add that in and get round to testing, should be able to tell you if it's worked or not pretty soon.

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

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

Why is the rotation missing when I animate? 1 Answer

Rotate 180 degrees over x axis over time 1 Answer

Rotation Question in Top-down 3D Game 0 Answers

Player wont follow touch controls? 1 Answer

Getting world coordinates for UI elements relative to a camera displaying to a render texture 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