|
| 29 Aug 2016 11:17 PM |
I'm making a tank, I've got the turret to spin around the Y rotation axis perfectly fine, However when I tried to rotate the actual cannon up and down, It messes up ~1/4 the time When the tank is pointed completely forward, it aims up and down perfectly, When the tank is rotated to the left or right or behind, Its off.
Im assuming because Im only dealing with the X and Y axis in my script, and when you rotate, Im no longer dealing with the X axis im dealing with the Z axis.
local diff = mouse.Hit.p - tank.Gun.PrimaryPart.Position local ang = math.deg(math.atan2(diff.X,diff.Y)) tank.Constraints.GunHinge.TargetAngle = ang |
|
|
| Report Abuse |
|
|
|
| 29 Aug 2016 11:36 PM |
One thing you could try is:
/| / | / | / | / | MAG / | Delta - Y / | / | / | / o | -------
let o be theta to rotate by....... local angleToRotateUpOrDown = math.asin(Delta-Y/MAG)
Where mag is always positive since its the total distance from the pivot point to the target Delta-Y is the difference in height of the target and pivot point's y-axis.....
Using this instead of trying to use opp/adj guarantees a value that isn't based on the x or z axis... it is based on distance and the difference in height... |
|
|
| Report Abuse |
|
|
|
| 29 Aug 2016 11:45 PM |
Although as I speak of it, this is only effective in the case that the tank is always level.... Otherwise you should consider using dot product to obtain an angle between the lookVector of the cannon and the direction of the target from the cannon....
|A| |B| Cos(theta) = A.X * B.X + A.Y * B.Y + A.Z * B.Z
then you can solve for theta.... A is the lookVector of the cannon... B is the direction of the target from the cannon...
You can filter out A.X or A.Z...
If you rotate the y-axis to align the cannon with the direction first then the A.X and B.X or the A.Z and B.Z should match up and you can ignore one or the other... |
|
|
| Report Abuse |
|
|
|
| 29 Aug 2016 11:46 PM |
| I tried something along these lines before, how would you do it your way? |
|
|
| Report Abuse |
|
|
|
| 29 Aug 2016 11:48 PM |
| I would show my old way to you however it didn't save. It didn't work whatsoever however Im not the most intelligent when it comes to this. |
|
|
| Report Abuse |
|
|
|
| 30 Aug 2016 12:13 AM |
wat grade do you lern this stuf in
im a mlg |
|
|
| Report Abuse |
|
|
|
| 30 Aug 2016 01:11 AM |
local Cannon = script.Parent.Cannon; local Base = script.Parent.Base; local Hinge = script.Parent.Hinge; local offsetHinge2Cannon = Hinge.CFrame:inverse()*Cannon.CFrame; local offsetBase2Hinge = Base.CFrame:inverse() * Hinge.CFrame; local LookAt = script.Parent.LookAt;
while(wait())do local dir2LookAtFromBase = (LookAt.Position - Base.Position); -- make the base's look vector face the target via y-axis Base.CFrame = CFrame.new(Base.Position) * CFrame.Angles(0,math.pi + math.atan2(dir2LookAtFromBase.X, dir2LookAtFromBase.Z),0) * CFrame.Angles(math.pi/-8,0,0); -- update hinge's location for this example which ignores welds Hinge.CFrame = Base.CFrame * offsetBase2Hinge; -- get the direction from the hinge(pivot) local dir2LookAtFromHinge = (LookAt.Position - Hinge.Position).unit -- project the unit vector of the direction on to the lookvector of the hinge itself local lv = Hinge.CFrame.lookVector; local projectedScalar = dir2LookAtFromHinge:Dot(lv); -- since lv and dir2LookAtFromHinge are both unit vectors the dot product simplifies to cos(theta) from A B cos(theta) local theta = math.acos(projectedScalar); -- since cos is only flipped horizontally we need to manually flip it by check if the y of the direction is negative if(lv.Y > dir2LookAtFromHinge.Y)then theta = -1 * theta; end -- update cannon cframe Cannon.CFrame = Hinge.CFrame * CFrame.Angles(theta,0,0) * offsetHinge2Cannon;
end
this is a example which uses all the parts aligned initially with their look vectors in same direction... This doesn't use welds, but it shows that even though the base could be going up hill or down hill, the angle of the cannon is matched via the look vector and not just the height difference... The height difference could work as well, but when you have the item welded or so then the 0 degree frame could be rotated non-parallel with coordinate system....
Basically the dot method approach will work because it basically projects the direction of the target onto the look vector of the hinge which is at a constant position in relation to the base which rotates on it's y-axis so that the lookVector and the directional vector are essentially in the same plane just an angle apart which is then translated to the rotation about the x-axis to make the cannon's look vector face the target's height... I will just upload the example and you can play with it to kinda learn it.
https://www.roblox.com/item.aspx?id=491779687
Fully documented... Not exactly optimized cause I just threw it together, but you get the point. |
|
|
| Report Abuse |
|
|
|
| 30 Aug 2016 10:31 AM |
Well I tried to implement this and failed, Im guessing its because you think Im using CFrame and not constraints. I'm trying to find one angle I need so I can rotate the gun upwards compared to the lookvector and mouse.hit angle
local dir2LookAtFromBase = (mouse.Hit.p - basePart.Position); basePart.CFrame = CFrame.new(basePart.Position) * CFrame.Angles(0,math.pi + math.atan2(dir2LookAtFromBase.X, dir2LookAtFromBase.Z),0) * CFrame.Angles(math.pi/-8,0,0); gunPart.CFrame = basePart.CFrame * offsetBase2Hinge; local dir2LookAtFromHinge = (mouse.Hit.p - gunPart.Position).unit local lv = gunPart.CFrame.lookVector; local projectedScalar = dir2LookAtFromHinge:Dot(lv); local theta = math.acos(projectedScalar); if(lv.Y > dir2LookAtFromHinge.Y)then theta = -1 * theta; end local ang = math.deg(theta) |
|
|
| Report Abuse |
|
|
|
| 30 Aug 2016 10:36 AM |
I was successfully able to fix it using simple lookvectors and comparing their dot, however the problem is it only works when the turret is facing the mouse, and is off when the turret hasnt rotated to the mouse yet
local diff2 = (mouse.Hit.p - gunPart.Position).unit local dir = turretPart.CFrame.upVector* -1 local ang = math.acos(diff2:Dot(dir)) --local ang = math.deg(math.atan2(math.max(math.abs(diff2.X),math.abs(diff2.Z)),diff2.Y)) tank.Constraints.GunHinge.TargetAngle = math.deg(ang)+90 |
|
|
| Report Abuse |
|
|
|
| 30 Aug 2016 10:37 AM |
Ignore the comment its only four lines
local diff2 = (mouse.Hit.p - gunPart.Position).unit local dir = turretPart.CFrame.upVector* -1 local ang = math.acos(diff2:Dot(dir)) tank.Constraints.GunHinge.TargetAngle = math.deg(ang)+90 |
|
|
| Report Abuse |
|
|
|
| 30 Aug 2016 12:26 PM |
Messed with it a little local diff2 = (mouse.Hit.p - gunPart.Position).unit local dir = turretPart.CFrame.lookVector local ang = math.acos(diff2:Dot(dir)) tank.Constraints.GunHinge.TargetAngle = math.deg(ang)
Right now it works great for anything below the gun of the tank aswell as it works as long as the turret is rotated towards the mouse.
It does not work when the turret is not quite in line with the mouse (It goes way low) It does not work when the mouse is above the gun, it starts to lower at the same angle it is above it
Please help |
|
|
| Report Abuse |
|
|
|
| 30 Aug 2016 12:31 PM |
local diff2 = (mouse.Hit.p - gunPart.Position).unit local dir = turretPart.CFrame.lookVector local ang = math.acos(diff2:Dot(dir)) if diff.Y>0 then ang = ang * -1 end tank.Constraints.GunHinge.TargetAngle = math.deg(ang)
Made this, fixed the second bug. The rotation bug still active. |
|
|
| Report Abuse |
|
|
|
| 30 Aug 2016 01:54 PM |
local diff2 = (mouse.Hit.p - gunPart.Position).unit local dir = turretPart.CFrame.lookVector local ang = math.acos(diff2:Dot(dir)) if diff2.Y < dir.Y then ang = ang * -1 end tank.Constraints.GunHinge.TargetAngle = math.deg(ang)
try that.... your checking if the difference in y position is > 0... you could have your target vector higher than the diff but still have a diff.Y > 0... as its a unit vector... so what you want to do is compare the diff's y slope with the look vectors as shown above.... may have to adjust the < sign to >, I am not sure on your setup.... but you want to change theta to negative only when the direction to target has a lower slope than the look vector.... |
|
|
| Report Abuse |
|
|
|
| 30 Aug 2016 02:06 PM |
[[It does not work when the turret is not quite in line with the mouse (It goes way low)]]
that's because the vectors are not in the same plane... They need to be in the same plane otherwise the offset can affect the angle too..
Try to solve this:
1. You know for the angle theta to be purely up/down the vectors need to be in the same plane....
2. The direction(diff2) points in the plane from the origin to the target.... The lookVector does not....
3. Basically you want to take the look vector and the diff2 and align them in the same plane.... One way you could do that is like so:
local diff2 = (mouse.Hit.p - gunPart.Position); -- that should align the vector diff2 with the look vector in the same plane without having excess data diff2 = (( turretPart.CFrame * CFrame.new( 0, diff2.Y, -math.abs( diff2.Z ) ) ).p - gunPart.Position).unit; local dir = turretPart.CFrame.lookVector local ang = math.acos(diff2:Dot(dir)) if diff.Y>0 then ang = ang * -1 end tank.Constraints.GunHinge.TargetAngle = math.deg(ang)
|
|
|
| Report Abuse |
|
|
|
| 30 Aug 2016 02:09 PM |
| Works a bit better actually, however it still doesnt fix the problem whent he turret mouse arn aline. |
|
|
| Report Abuse |
|
|
|
| 30 Aug 2016 02:31 PM |
THANKYOU
You've solved it, I owe you my life! Sorry I didnt see your second post. It works perfectly. Thankyou |
|
|
| Report Abuse |
|
|
|
| 30 Aug 2016 02:54 PM |
Ok so I have come up with the way to align their planes........ I will give you my code for you to implement....
Create 3 parts in workspace... V1 V2 Origin
Add the code below in a script and run it....
V1 is placed in relation to origin.... V1 is used as a pseudo look vector.... Ie the lookVector extends from origin to V1... In your code V1 is really just the lookVector of the gunPart or whatever...
V2 is your target part... this would be your mouse position....
---------------CODE----------------------- -- get V1 and V2 as a vector relative to origin local V1 = (workspace.V1.Position-workspace.Origin.Position); local V2 = (workspace.V2.Position-workspace.Origin.Position);
-- artificial look vector based on V1 from origin local LookVectorCFrame = CFrame.new(workspace.Origin.Position, workspace.V1.Position); local LookVector = LookVectorCFrame.lookVector;
-- get the distance without the height... aka the adjacent end of the triangle -- this is the distance of origin to the target without the y-axis local V2DistanceNoY = math.sqrt(V2.X^2 + V2.Z^2);
-- move the position of v2 ontop of V1 vector -- place at origin, add lookVector(magnitude 1) multiplied by the distance without the Y-axis, -- finally add the yHeight with respect to the origin(AKA V2.Y) workspace.V2.Position = workspace.Origin.Position + LookVector * V2DistanceNoY + Vector3.new(0,V2.Y,0);
-- update V2 so that it is now a unit vector as well as v1 V2 = (workspace.V2.Position-workspace.Origin.Position).unit; V1 = V1.unit;
-- now we can get the angle from the dot product... -- this angle still has to be translated to negative or positive based on the direction of V1 and V2... if V2.Y is less than V1.Y -- then it should be negated because the target is actually beneath our look vector
print(math.deg(math.acos(V2:Dot(V1)))) |
|
|
| Report Abuse |
|
|
|
| 30 Aug 2016 02:55 PM |
| Well in that case the above is not necessary lol... Glad it works! |
|
|
| Report Abuse |
|
|
|
| 30 Aug 2016 03:26 PM |
Actually it isn't working as well as I saw it worked at first.
I made your code into this and well It doesnt move much. It goes from around 15 degrees to 30 and isnt very perdictable.
local V1 = (gunPart.CFrame.lookVector-gunPart.Position); local V2 = (mouse.Hit.p-gunPart.Position); local LookVectorCFrame = CFrame.new(gunPart.Position, gunPart.CFrame.lookVector); local LookVector = LookVectorCFrame.lookVector; local V2DistanceNoY = math.sqrt(V2.X^2 + V2.Z^2); local poser = gunPart.Position + LookVector * V2DistanceNoY + Vector3.new(0,V2.Y,0); V2 = (poser-gunPart.Position).unit; V1 = V1.unit; local ang = math.deg(math.acos(V2:Dot(V1))) print(ang) tank.Constraints.GunHinge.TargetAngle = ang |
|
|
| Report Abuse |
|
|
|
| 30 Aug 2016 03:46 PM |
you gotz to learn some good trig to mess with lookvectors using atan2 on everything obviously isnt the solution especially if you have no idea what it does |
|
|
| Report Abuse |
|
|
|
| 30 Aug 2016 08:48 PM |
[[gunPart.CFrame.lookVector-gunPart.Position]]
wtf is that lol?
why would you subtract a position from a lookVector.... Positions represent placement and lookVectors represent orientation... |
|
|
| Report Abuse |
|
|
|
| 30 Aug 2016 08:49 PM |
| If you don't mind could you upload the tank and the code you have or something? |
|
|
| Report Abuse |
|
|
|
| 30 Aug 2016 09:33 PM |
Well during that bit I wasn't really thinking about what to do, I just was kinda doing what you said.
Anyways its here, unlocked, The script is a localscript in starterplayer
https://www.roblox.com/games/486473956/Tank-Trouble |
|
|
| Report Abuse |
|
|
|
| 30 Aug 2016 09:58 PM |
With some manipulation of the original code i gave you: Origin is the point that the vectors originate from LookVector is a unit vector(direction with magnitude 1) Target is a position vector
-- local V1 = (workspace.V1.Position-workspace.Origin.Position); -- local V2 = (workspace.V2.Position-workspace.Origin.Position); function GetAngle(Origin, LookVector, Target) local V2 = Target-Origin; -- get the distance without the height... aka the adjacent end of the triangle -- this is the distance of origin to the target without the y-axis local V2DistanceNoY = math.sqrt(V2.X^2 + V2.Z^2); local LVN = Vector3.new(LookVector.X,0, LookVector.Z).unit; -- move the position of v2 ontop of V1 vector -- place at origin, add lookVector(magnitude 1) multiplied by the distance without the Y-axis, -- finally add the yHeight with respect to the origin(AKA V2.Y) V2 = ((LVN) * V2DistanceNoY + Vector3.new(0,V2.Y,0)).unit -- now we can get the angle from the dot product... -- this angle still has to be translated to negative or positive based on the direction of V1 and V2... if V2.Y is less than V1.Y -- then it should be negated because the target is actually beneath our look vector local dotProduct = math.min(V2:Dot(LookVector),1); local theta = math.deg(math.acos(dotProduct)); if(V2.Y < LookVector.Y)then theta = theta * -1; end print(theta); return theta; end
GetAngle(workspace.Origin.Position, (workspace.V1.Position-workspace.Origin.Position).unit, workspace.V2.Position); |
|
|
| Report Abuse |
|
|
|
| 30 Aug 2016 10:46 PM |
That worked with a angle of 45.482823246519 45.482823246519 45.482823246519 45.482823246519 45.482823246519 45.482823246519 45.482823246519 45.482823246519
Which seamed about right
How to implant it because we arnt dealing with bricks now? |
|
|
| Report Abuse |
|
|