- Home /
Moving selected unit to location in space rts based on screen touch
I have a space rts game im making, and i have my code set up for my ships to move to locations, but i cannot accurately get the location in world space based on touch. I can rotate my camera around in 3d space, but i want to be able to move ships like "sins of the solar empire".
If my camera is on the side of my ship and if i touch in front i want the target position to be forward in front of it and up / below it. If my camera is above i want it to move my ship on that axis (not vertically) and just move it like im looking down upon it like command and conquer style.
How would i get this effect and still be able to rotate my camera freely? (and accomodate for my camera being at uneven rotations)
I assumed i could have 3 grids that for the 3 axis i would move on, and just raycast to these grids' colliders and get the points that wya, but that seems inefficient, as i eventually want to generate random maps.
This shows the 3 grids i meant and each is invisible and meant to detect each touch's raycast to determine location to move the ship:
How would i go about doing this? By the way this is for an android 3.2 tegra 2 10.1 tablet specs.
I hope i explained this enough, if not just ask to clerify or a find a video on youtube.
Answer by senad · Jan 12, 2012 at 09:39 AM
So did I understand you correctly, you want your ship to move on a plane which is orthogonal to the viewing direction?
If this is what you want you could setup an invisible plane which goes through your ships position and rotates with the camera. You can then do a ray cast with this plane in order to determine the ship's new position.
If you do the plane in geometry in unity, you can use the unity raycasting functionality. Otherwise, you could do the collision calclulation yourself. (collision of ray with plane)
Ok that sound slike a plan, but what if i am selecting a fleet of ships? Do i just put this plane on the middle one? How do i know which one is middle? And then how do i get them to not just all pile into that one point? Wouldnt creates these planes be resource intensive on a mobile device? Im always trying to make my code in respect to mobile performanc ein cas ei have huge object counts.
And then how do make this plane bigger/ smaller dependant on camera pov (i zoom using pov not distance)? Wouldnt this also make it resource intensive?
If you have many ships scattered in 3D I imagine it to be difficult to move them by a single touch/click. So the answer kind of depends on how you have figured out they should be moved.
What you could do is to construct a bounding box around all of them and then take the middle of that.
In order to not to pile all in one point you have to move them all by the same vector. I do not know though if this will feel and look good. $$anonymous$$aybe you will have experiment with the controls a bit.
This algorithm should scale well since you would only construct the plane for once no matter how many objects you have.
For the performance on iphone, I do not know, but adding a plane and doing the ray intersection calculations should not be very time consu$$anonymous$$g.
Is there a way to scale this plane depending on my camera fov and render screen size?
The easiest would be to have an infinite plane, but you can not have it, of you define the plane in geometry.
Since there is now performance penalty depending on how big the plane is, I would just chose one which is big enough to cover all sensible cases.
You could make it fit your viewing frustum, but it is not necessary and will cost you additional performance.
Answer by Nodrap · Jan 12, 2012 at 08:48 AM
Your cameras view matrix takes the ships 3D position and translates it to the screens X, Y (&Z) to render it. If you do the reverse to the click position (and add the ships distance from the camera as the Z) then it should return a 3D point in the plane of travel you are after.
Doesn't work when scaling using FOV for zoom effects. Otherwise would have worked nicely.
Answer by 1337GameDev · Jan 12, 2012 at 09:05 AM
What do u mean by reverse? How would I go about that, in code? If I use the X and y from the touch position then the position will be off if I just use the distance from camera to ship as z component. Wouldn't this coordinate also be in local position referenced from the camera? How would I get this as a real world position relative to the world origin then?
(Use the "add new comment" button to reply rather than answering. Yes it's a bit weird!) The reverse is getting the inverse of the matrix which should be easy with most maths libraries. So if matrix $$anonymous$$ is applied to A and returns position B, applying the inverse of $$anonymous$$ to B will return it to A. You will also need to ensure you treat the centre of the screen as 0,0
I am a bit confused. Can you show an example? (I learn from examples of code). Not that im trying to have people do work for me, but i just dont even know where to begin.
Ok, very rough code in C#:
float targetDepth = (cameraPos - targetPos).length; Vector3 screenClick = new Vector3(screenTouchX-screenCentreOffsetX, screenTouchY-screenCentreOffsetY, targetDepth); Vector3 destinationPos = screenClick * camera$$anonymous$$atrix.inverse;
Things to check are the scale of the coordinates in Z and its +- sign (try both). I would first test it by placing the target in the middle of the screen and clicking on it (thus passing vector (0, 0, targetDepth) ) and comparing what is returned with its actual position. You may need to scale the Z by some factor. Then start testing along one axis and possibly scale again too. The third axis should then drop out.
Can you explain your methods and frame of thought. I don't understand what your doing in this code segment. Where is camera$$anonymous$$atrix defined? Andnif its a member of camera, what does it give? I am on a tablet, not a pc, so why screenclick? Where are the offsets defined and what do these tell? And how do I find target position in the first line you gave?
Not to complain, but you should expect questions if you spit out code with no comments and explanation in the lines of code.
I was assu$$anonymous$$g you only needed light guidance - I do have better things to do. If you are struggling here I fear the project of creating a 3D RTS may be a little too complex. But anyway...
"If it's a member of camera" - Yes it is, a simple read of the manual would have answered that one. If you don't understand what a view matrix does, you'll have to look for a tutorial. If you don't understand how matrices and vectors work, you'll need another tutorial.
"screenClick" - I was writing generic code for any click/touch device. Whatever device it will return its position (you may need to reverse some axis depending on where it treats the origin). If your screen is 800x600 then the centre offsets would be 400 and 300, so that when you click on the centre you get (400-400, 300-300, z) which will be a vector that is dead centre and the length from the camera to the target object (the ship you are moving).
There is one other thing that will need adjusting I've realised, and that the X/Y from the screen will need to be scaled depending on how far away the target ship is. This scaling is calculated by the camera's depth of field. Unfortunately working out this is a little complicated, so I'd suggest trial and error, or try and figure out the trig you will need to take the FOV angle and apply it to the views scaling. Sorry, but this is getting beyond $$anonymous$$chable in a forum. There may be a better way that someone else can suggest.
Good luck.