Hello guys. During last week, I tried to do arms for my robot. But I have 1 problem which I can’t solve - his arm rotates by 1 axis inversion.
local RunService = game:GetService("RunService")
local ServerStorage = game:GetService("ServerStorage")
local Modules = ServerStorage:WaitForChild("Modules")
local Robot = script.Parent.Parent
local Distance = 100
local SaveDelta = 0
local FrameRate = 15
local PreviousRenderFinished = true
local LookAtPart = workspace.CameraTarget
local DotAPart = workspace.DotA
local DotBPart = workspace.DotB
local DotCPart = workspace.DotC
local DotRTA = workspace.DotRelativeToAttachment
local DirectionVis = Instance.new("Part")
DirectionVis.Color = Color3.fromRGB(255, 0, 255)
DirectionVis.Anchored = true
DirectionVis.CanCollide = false
DirectionVis.Size = Vector3.new(0.001, 2, 2)
DirectionVis.Parent = workspace
local CFDisplay = workspace.CFrameDisplay
local RobotMeta = {}
RobotMeta.__index = RobotMeta
local function CFLookAt2(eye, target, plane)
local VectorX, VectorY, VectorZ = plane and plane.XVector or Vector3.xAxis, plane and plane.YVector or Vector3.yAxis, plane and plane.ZVector or Vector3.zAxis
local lookVector = target - eye
if lookVector:Dot(lookVector) <= 1e-5 then
return CFrame.new(eye)
else
lookVector = lookVector.Unit
end
if math.abs(lookVector.Y) >= 0.9999 then
return CFrame.fromMatrix(eye, VectorX, math.sign(lookVector.Y) * VectorZ)
else
local rightVec = lookVector:Cross(VectorY).Unit
local upVec = rightVec:Cross(lookVector).Unit
return CFrame.fromMatrix(eye, rightVec, upVec)
end
end
function RobotMeta.Initialize()
local self = {
Motors = {
}
}
for _, object in pairs(Robot.Motors:GetChildren()) do
print(object)
self.Motors[string.match(object.Name, "Motor(.*)")] = object
if object.ClassName == "RigidConstraint" then
object.Attachment0:SetAttribute("InitialCFrame", object.Attachment0.CFrame)
object.Attachment1:SetAttribute("InitialCFrame", object.Attachment1.CFrame)
end
end
return setmetatable(self, RobotMeta)
end
function RobotMeta:LookAt(Target, MoveEyes)
local PistonAtt0 = self.Motors.NeckPiston.Attachment0
local PistonAtt1 = self.Motors.NeckPiston.Attachment1
local Direction = PistonAtt0.WorldCFrame:Inverse() * Target
Direction = Direction.Unit
local DirectionCF = CFLookAt2(Vector3.zero, Direction.Unit)
PistonAtt1.CFrame = PistonAtt1:GetAttribute("InitialCFrame") * DirectionCF:Inverse()
local LeftAtt = self.Motors.LeftCamera.Attachment0
local LeftDirCFrame = CFLookAt2(Vector3.zero, (Target - LeftAtt.WorldCFrame.Position).Unit)
LeftAtt.WorldCFrame = CFrame.new(LeftAtt.WorldCFrame.Position) * LeftDirCFrame
local RightAtt = self.Motors.RightCamera.Attachment0
local RightDirCFrame = CFLookAt2(Vector3.zero, (Target - RightAtt.WorldCFrame.Position).Unit)
RightAtt.WorldCFrame = CFrame.new(RightAtt.WorldCFrame.Position) * RightDirCFrame
end
local Flick = 0
function RobotMeta:MoveArm(Side, Target)
if Side == "Left" then
local ArmSeg1Length = 0.975
local ArmSeg2Length = 0.825
local ShoulderAtt0 = self.Motors.LeftShoulder.Attachment0
local ShoulderAtt1 = self.Motors.LeftShoulder.Attachment1
local LowerArmAtt0 = self.Motors.LeftLowerArm.Attachment0
local LowerArmAtt1 = self.Motors.LeftLowerArm.Attachment1
local Direction = ShoulderAtt0.WorldCFrame:Inverse() * Target
DotRTA.CFrame = CFrame.new(Direction)
local DirectionPlane = Vector3.new(Direction.X, 0, Direction.Z).Unit
DirectionPlane = CFLookAt2(Vector3.zero, DirectionPlane)
DirectionVis.CFrame = ShoulderAtt0.WorldCFrame.Rotation:Inverse() * DirectionPlane + ShoulderAtt0.WorldCFrame.Position
local DirA, DirB = self.CalculateIK(DirectionPlane + ShoulderAtt0.WorldCFrame.Position, Target, ShoulderAtt0.WorldCFrame.Position, ArmSeg1Length, ArmSeg2Length)
local Rot = workspace.DataChanger:GetAttribute("Rotation")
DirA = DirectionPlane * CFrame.fromEulerAngles(-math.pi/2, 0, 0) * DirA
DirB = DirectionPlane * DirB
DotRTA.Position = LowerArmAtt1:GetAttribute("InitialCFrame") * DirB
local LookVector = DirA
local RightVector = DirectionPlane.RightVector
local UpVector = RightVector:Cross(LookVector)
local DirCFrameA = CFrame.fromMatrix(Vector3.zero, -LookVector, -UpVector, -RightVector)
LookVector = DirB
RightVector = DirectionPlane.RightVector
UpVector = RightVector:Cross(LookVector)
local DirCFrameB = CFrame.fromMatrix(Vector3.zero, RightVector, UpVector, LookVector) * CFrame.Angles(0, -math.pi/2, 0)
local ShoulderDir = DirCFrameA:Inverse()
local LowerArmDir = DirCFrameB
CFDisplay.CFrame = ShoulderDir
ShoulderAtt1.CFrame = ShoulderAtt1:GetAttribute("InitialCFrame") * ShoulderDir
LowerArmAtt1.CFrame = LowerArmAtt1:GetAttribute("InitialCFrame") * LowerArmDir
end
end
local Plane2D = workspace.Plane2D
function RobotMeta.CalculateIK(Plane, Target, Start, LengthC, LengthA)
local LengthB = (Target - Start).Magnitude
local DotA, DotC = Plane:Inverse() * Start, Plane:Inverse() * Target
local TargetAtan = (DotC - DotA).Unit
local Atan = math.atan2(TargetAtan.Y, TargetAtan.Z)
if (LengthC + LengthA < LengthB) then
local DirA = Vector3.new(0, math.sin(Atan), math.cos(Atan))
local DirB = Vector3.new(0, 0, -1)
return DirA, DirB
end
local AngleA = math.acos((LengthB^2+LengthC^2-LengthA^2) / (2*LengthB*LengthC))
local AngleB = math.acos((LengthA^2+LengthC^2-LengthB^2) / (2*LengthA*LengthC))
Atan %= math.pi*2
AngleA %= math.pi*2
AngleB %= math.pi*2
local AngleB2 = AngleB
AngleA = Atan + AngleA
AngleB2 = -AngleB2
AngleB = (AngleA + AngleB + math.pi) % (math.pi*2)
local DirA = Vector3.new(0, math.sin(AngleA), math.cos(AngleA))
local DirB = Vector3.new(0, math.sin(AngleB), math.cos(AngleB))
local DirB2 = Vector3.new(0, math.sin(AngleB2), math.cos(AngleB2))
DotAPart.Position = DirectionVis.CFrame.Position
DotBPart.Position = DirectionVis.CFrame * (DirA * LengthC)
DotCPart.Position = DirectionVis.CFrame * (DirA * LengthC + DirB * LengthA)
return DirA, DirB2
end
local RobotFunctions = RobotMeta.Initialize()
RunService.Heartbeat:Connect(function(Delta)
SaveDelta += Delta
if SaveDelta >= 1 / FrameRate and PreviousRenderFinished then
SaveDelta %= 1 / FrameRate
PreviousRenderFinished = false
--RobotFunctions:RenderFrame()
--RobotFunctions:GenerateNavigationMesh()
--RobotFunctions:LookAt(LookAtPart.Position)
RobotFunctions:MoveArm("Left", LookAtPart.Position)
PreviousRenderFinished = true
end
end)
Can someone please help me to get rid from 1 axis inversions?