{"name":"attachChild","operator":null,"title":"attachChild","type":"command","url":"https://community.bistudio.com/wiki/attachChild","revid":378902,"updated":"2026-08-11T14:56:33Z","groups":["PhysX"],"status":"ok","replaced_by":[],"games":[{"game":"arma3","name":"Arma 3","version":"2.22"}],"since":{"game":"arma3","name":"Arma 3","version":"2.22"},"arma3_since":"2.22","branch":null,"locality":{"argument":"local","effect":"global","server_exec":false},"exec":null,"description":"Attaches a child object to a parent, similar to attachTo but instead of a rigid/forced attachment its using a PhysX joint.\n\n> [!NOTE]\n> For more information see [NVIDIA docs](https://docs.nvidia.com/gameworks/content/gameworkslibrary/physx/guide/Manual/Joints.html).\n\nNote that the joint parameters XYZ orientations, are according to the localFrame of the joint. swingZ/swingY/twist being Yaw/Roll/Pitch, can be changed if the joint itself is rotated, because the joint rotation moves the whole axis.","syntaxes":[{"syntax":"[parent, child] attachChild [jointType, localFrameParent, localFrameChild, miscFlags, jointDescription]","since":null,"effect":null,"exec":null,"params":[{"name":"parent","type":"Object","optional":false,"default":null,"description":"the parent object that another object is attached to. Must be a Transport vehicle like Car/Tank (Maybe helicopter/airplane works?).","types":["Object"],"since":null,"text":"parent: Object - the parent object that another object is attached to. Must be a Transport vehicle like Car/Tank (Maybe helicopter/airplane works?)."},{"name":"child","type":"Object","optional":false,"default":null,"description":"the object being attached onto the parent. Must be a Transport vehicle like Car/Tank (Maybe helicopter/airplane works?).","types":["Object"],"since":null,"text":"child: Object - the object being attached onto the parent. Must be a Transport vehicle like Car/Tank (Maybe helicopter/airplane works?)."},{"name":"jointType","type":"String","optional":false,"default":null,"description":"currently only \"6DOFJoint\" and \"RevoluteJoint\" and \"FixedJoint\"\n\n**6DOFJoint**\nAllows to configure all axis (XYZ translation, Pitch/Yaw/Roll rotation) limits and drives.\n**RevoluteJoint**\nOnly allows rotation around the X axis, a Revolute joint can also be implemented with a 6DOFJoint and the appropriate limits (internally it is implemented exactly like that)\n**FixedJoint**\nLimited in all axis, it essentially works like a PhysX based attachTo.","types":["String"],"since":null,"text":"jointType: String - currently only \"6DOFJoint\" and \"RevoluteJoint\" and \"FixedJoint\"\n\n**6DOFJoint**\nAllows to configure all axis (XYZ translation, Pitch/Yaw/Roll rotation) limits and drives.\n**RevoluteJoint**\nOnly allows rotation around the X axis, a Revolute joint can also be implemented with a 6DOFJoint and the appropriate limits (internally it is implemented exactly like that)\n**FixedJoint**\nLimited in all axis, it essentially works like a PhysX based attachTo."},{"name":"localFrameParent","type":"Array","optional":false,"default":null,"description":"the Position and orientation, in parent's model-space of where the joint will be placed.\n\nAn Array of 3 elements [position, upPos, dirPos]\n\nEach element can either be a Vector (3-element array of Number) or a Memory point name (String).\n\nAn important Caveat when using Vectors is that dir and up are not direction vectors, but positions.\n\nEssentially, upPos/dirPos would be the model-space coordinates of where the memory point would be.\n\nFor example:\n\n```sqf\nprivate _jointPos = [0, 0, 0];\nprivate _vectorDir = [0, 1, 0];\nprivate _vectorUp = [0, 0, 1];\n[_jointPos, _jointPos vectorAdd _vectorDir, _jointPos vectorAdd _vectorUp];\n```","types":["Array"],"since":null,"text":"localFrameParent: Array - the Position and orientation, in parent's model-space of where the joint will be placed.\n\nAn Array of 3 elements [position, upPos, dirPos]\n\nEach element can either be a Vector (3-element array of Number) or a Memory point name (String).\n\nAn important Caveat when using Vectors is that dir and up are not direction vectors, but positions.\n\nEssentially, upPos/dirPos would be the model-space coordinates of where the memory point would be.\n\nFor example:\n\n```sqf\nprivate _jointPos = [0, 0, 0];\nprivate _vectorDir = [0, 1, 0];\nprivate _vectorUp = [0, 0, 1];\n[_jointPos, _jointPos vectorAdd _vectorDir, _jointPos vectorAdd _vectorUp];\n```"},{"name":"localFrameChild","type":"Array","optional":false,"default":null,"description":"the position and orientation, in child's model-space of where the joint will be placed.","types":["Array"],"since":null,"text":"localFrameChild: Array - the position and orientation, in child's model-space of where the joint will be placed."},{"name":"miscFlags","type":"Array","optional":true,"default":"false","description":"[(collisionEnabled, breakForce)]\n\n****\ncollisionEnabled: Boolean  - When false, disables collision between the two joint-ed objects\n****\nbreakForce: Number (Optional, Default: -1)\n****\nlimitsAreForces?","types":["Array"],"since":null,"text":"miscFlags: Array - [(collisionEnabled, breakForce)]\n\n****\ncollisionEnabled: Boolean (Optional, Default: false) - When false, disables collision between the two joint-ed objects\n****\nbreakForce: Number (Optional, Default: -1)\n****\nlimitsAreForces?"},{"name":"jointDescription","type":"Array","optional":true,"default":"0","description":"this specifies the behavior/limits of the joint.\n\n[(linearLimit, swingLimit, twistLimit, drives)]\n\nNote that all are optional. Passing an empty array is equivalent to using a \"FixedJoint\" type\n\n<div class=\"_description\">\n**linearLimit**\nArray - Linear limit specifies the joints permitted translation along the XYZ axis.\nThere are three types of linear limits, fully locked, per-axis limit and distance limit.\n\n<div class=\"_description\">\n**Fully Locked:**\n[]\nEmpty array, will completely lock the XYZ translational axes, only allowing rotational movement (If allowed in the swing/twist limits)\n**Per axis:**\n[limitX, limitY, limitZ]\n<div class=\"_description\">\n**limit*:**\nArray - [lowerLimit, upperLimit, springParameters] <div class=\"_description\">\n**lowerLimit:**\nNumber - The minimum permitted offset on the axis\n**upperLimit:**\nNumber - The maximum permitted offset on the axis\n upperLimit must be larger than lowerLimit\n**springParameters:**\nArray - [(restitution, spring, damping)]\nAll spring parameters are optional, but for the linear limits, atleast an empty array must be provided.\n**restitiution:**\nNumber  - Must be between 0-1.\n Controls the amount of bounce when the joint hits a limit.\n A restitution value of 1.0 causes the joint to bounce back with the velocity which it hit the limit.\n A value of zero causes the joint to stop dead.\n [NVIDIA docs](https://docs.nvidia.com/gameworks/content/gameworkslibrary/physx/apireference/files/classPxJointLimitParameters.html#cf208a0f1e54fb8e9219af1e0357d4a9)\n**spring:**\nNumber (Optional, Default: 0) - Must be 0 or greater.\n if greater than zero, the limit is soft, i.e. a spring pulls the joint back to the limit\n**damping:**\nNumber (Optional, Default: 0) - Must be 0 or greater. if spring is greater than zero, this is the damping of the limit spring\n**Distance Limit**\n[xLocked, yLocked, zLocked, distanceLimit, springParameters]\n <div class=\"_description\">\n***Locked:**\nBoolean - Whether the axis is completely locked and no translation is allowed along it\n**distanceLimit:**\nNumber - Distance on meters, as a radius/sphere around the joint.\n**swingLimit:**\nArray - [(swingX, swingZ, springParameters)]\nAll parameters are optional, the default is both swing axis being locked\nSwing limit comes in two types, cone and pyramid. Which variant is used depends on the datatype inside the swing parameter\nNote that cone cannot be combined with pyramid, either both are cone or both are pyramid.\nIf the swing limit is pi, the rotation around that axis is fully unlocked/free.<div class=\"_description\">\n**Cone limit:**\nswingZ: Number (Optional, Default 0/locked) - The rotation around the Z (up) axis, thus the yaw. Rotation in radians, between pi and pi.\n****\nswingY: Number (Optional, Default 0/locked) - The rotation around the Y (front/dir) axis, thus the roll. Rotation in radians, between pi and pi.\n**Pyramid limit:**\nswingZ: Array - [(min, max)] - Same rotation in radians as the cone limit, but it can be asymmetrical.\n****\nswingY:  Array - [(min, max)] - Same rotation in radians as the cone limit, but it can be asymmetrical.\n**twistLimit:**\nArray - [(twistLower, twistUpper, springParameters)]\nTwist is rotation about the X (right) axis, thus the pitch.\nLeft and right twist limits can be configured independently.\n<div class=\"_description\">\n**twist*:**\nNumber (Optional, Default: 0) - Rotation limit in radians, between -2pi and 2pi\n 0 means twist is locked, and 2*pi means its completely unlocked\n**drives:**\nArray - [(angularSwingDrive, angularTwistDrive, angularSlerpDrive, linearXDrive, linearYDrive, linearZDrive, limitsAreForces)]\nDrives allow to apply force into the joint on any of the axes.\nEach drive is a spring, one end being on the joint, and the other end being on the target specified by the commands:\nsetJointDrivePosition setJointDriveOrientation setJointDriveLinearVelocity setJointDriveAngularVelocity\nFor rotational drives there are two variants, Swing+Twist or SLERP (Spherical Linear Interpolation)\nSee [NVIDIA docs](https://docs.nvidia.com/gameworks/content/gameworkslibrary/physx/guide/Manual/Joints.html#drives)<div class=\"_description\">\n***Drive:**\nArray - [type, spring, damping, forceLimit]\n**type:**\nNumber - MUST be 0 (#TODO acceleration drive implementation?)\n\n**spring:**\nNumber - Same as springParameters above\n**damping:**\nNumber - Same as springParameters above\n**forceLimit:**\nNumber - The maximum force this drive c an apply to the joint\n**limitsAreForces:**\nBoolean (Optional, Default: true) - NOT IMPLEMENTED #TODO?","types":["Array"],"since":null,"text":"jointDescription: Array - this specifies the behavior/limits of the joint.\n\n[(linearLimit, swingLimit, twistLimit, drives)]\n\nNote that all are optional. Passing an empty array is equivalent to using a \"FixedJoint\" type\n\n<div class=\"_description\">\n**linearLimit**\nArray - Linear limit specifies the joints permitted translation along the XYZ axis.\nThere are three types of linear limits, fully locked, per-axis limit and distance limit.\n\n<div class=\"_description\">\n**Fully Locked:**\n[]\nEmpty array, will completely lock the XYZ translational axes, only allowing rotational movement (If allowed in the swing/twist limits)\n**Per axis:**\n[limitX, limitY, limitZ]\n<div class=\"_description\">\n**limit*:**\nArray - [lowerLimit, upperLimit, springParameters] <div class=\"_description\">\n**lowerLimit:**\nNumber - The minimum permitted offset on the axis\n**upperLimit:**\nNumber - The maximum permitted offset on the axis\n upperLimit must be larger than lowerLimit\n**springParameters:**\nArray - [(restitution, spring, damping)]\nAll spring parameters are optional, but for the linear limits, atleast an empty array must be provided.\n**restitiution:**\nNumber (Optional, Default: 0) - Must be between 0-1.\n Controls the amount of bounce when the joint hits a limit.\n A restitution value of 1.0 causes the joint to bounce back with the velocity which it hit the limit.\n A value of zero causes the joint to stop dead.\n [NVIDIA docs](https://docs.nvidia.com/gameworks/content/gameworkslibrary/physx/apireference/files/classPxJointLimitParameters.html#cf208a0f1e54fb8e9219af1e0357d4a9)\n**spring:**\nNumber (Optional, Default: 0) - Must be 0 or greater.\n if greater than zero, the limit is soft, i.e. a spring pulls the joint back to the limit\n**damping:**\nNumber (Optional, Default: 0) - Must be 0 or greater. if spring is greater than zero, this is the damping of the limit spring\n**Distance Limit**\n[xLocked, yLocked, zLocked, distanceLimit, springParameters]\n <div class=\"_description\">\n***Locked:**\nBoolean - Whether the axis is completely locked and no translation is allowed along it\n**distanceLimit:**\nNumber - Distance on meters, as a radius/sphere around the joint.\n**swingLimit:**\nArray - [(swingX, swingZ, springParameters)]\nAll parameters are optional, the default is both swing axis being locked\nSwing limit comes in two types, cone and pyramid. Which variant is used depends on the datatype inside the swing parameter\nNote that cone cannot be combined with pyramid, either both are cone or both are pyramid.\nIf the swing limit is pi, the rotation around that axis is fully unlocked/free.<div class=\"_description\">\n**Cone limit:**\nswingZ: Number (Optional, Default 0/locked) - The rotation around the Z (up) axis, thus the yaw. Rotation in radians, between pi and pi.\n****\nswingY: Number (Optional, Default 0/locked) - The rotation around the Y (front/dir) axis, thus the roll. Rotation in radians, between pi and pi.\n**Pyramid limit:**\nswingZ: Array - [(min, max)] - Same rotation in radians as the cone limit, but it can be asymmetrical.\n****\nswingY:  Array - [(min, max)] - Same rotation in radians as the cone limit, but it can be asymmetrical.\n**twistLimit:**\nArray - [(twistLower, twistUpper, springParameters)]\nTwist is rotation about the X (right) axis, thus the pitch.\nLeft and right twist limits can be configured independently.\n<div class=\"_description\">\n**twist*:**\nNumber (Optional, Default: 0) - Rotation limit in radians, between -2pi and 2pi\n 0 means twist is locked, and 2*pi means its completely unlocked\n**drives:**\nArray - [(angularSwingDrive, angularTwistDrive, angularSlerpDrive, linearXDrive, linearYDrive, linearZDrive, limitsAreForces)]\nDrives allow to apply force into the joint on any of the axes.\nEach drive is a spring, one end being on the joint, and the other end being on the target specified by the commands:\nsetJointDrivePosition setJointDriveOrientation setJointDriveLinearVelocity setJointDriveAngularVelocity\nFor rotational drives there are two variants, Swing+Twist or SLERP (Spherical Linear Interpolation)\nSee [NVIDIA docs](https://docs.nvidia.com/gameworks/content/gameworkslibrary/physx/guide/Manual/Joints.html#drives)<div class=\"_description\">\n***Drive:**\nArray - [type, spring, damping, forceLimit]\n**type:**\nNumber - MUST be 0 (#TODO acceleration drive implementation?)\n\n**spring:**\nNumber - Same as springParameters above\n**damping:**\nNumber - Same as springParameters above\n**forceLimit:**\nNumber - The maximum force this drive c an apply to the joint\n**limitsAreForces:**\nBoolean (Optional, Default: true) - NOT IMPLEMENTED #TODO?"}],"returns":{"type":"Nothing","types":["Nothing"],"description":"Do NOT depend on this staying nothing, it might change to be something.","text":"Nothing - Do NOT depend on this staying nothing, it might change to be something."},"form":"binary","operator":null,"left":{"text":"[parent, child]","types":["Array"]},"right":{"text":"[jointType, localFrameParent, localFrameChild, miscFlags, jointDescription]","types":["Array"]}}],"examples":[{"text":"Attach a Quad (varname towbar) to a HEMTT (varName vParent) and another HEMTT (varName vChild) to the Quad.\nEssentially using the Quad as a \"towbar\":\n\n```sqf\n_parentPos = [0, -5, 0]; // position on the hemtt\n_childPos = [0, 1, -0.2]; // position on the quad\n\n_jointDescription =\n[\n// Limits\n    // Linear\n    [], // Default is locked\n\n    // Swing\n    // [swing1 yaw, swing2 roll, springParams]\n    [\n        rad 45, // yaw\n        0 // roll\n    ],\n    // Twist pitch\n    // [twistLower, twistUpper, springParams]\n    [rad -20, rad 20], // Default is locked\n\n// Drives\n    [] // Default are none\n];\n\n_params = [\n    \"6DOFJoint\",\n    // From [pos,dir,up]\n    [_parentPos, _parentPos vectorAdd [0, 1, 0], _parentPos vectorAdd [0, 0, 1]],\n    // To [pos,dir,up]\n    [_childPos, _childPos vectorAdd [0, 1, 0], _childPos vectorAdd [0, 0, 1]],\n    // misc [collisions enabled]\n    [false],\n    _jointDescription\n];\n\n[vParent, towBar] attachChild _params;\n\n_parentPos = [0, -1, -0.2]; // Position on the quad\n_childPos = [0, 5, 0]; // Position on the hemtt\n\n_params = [\n    \"6DOFJoint\",\n    // From [pos,dir,up]\n    [_parentPos, _parentPos vectorAdd [0, 1, 0], _parentPos vectorAdd[0, 0, 1]],\n    // To [pos,dir,up]\n    [_childPos, _childPos vectorAdd [0, 1, 0], _childPos vectorAdd [0, 0, 1]],\n    // misc [collisions enabled]\n    [false],\n    _jointDescription\n];\n\n[towBar, vChild] attachChild _params;\n```","code":["_parentPos = [0, -5, 0]; // position on the hemtt\n_childPos = [0, 1, -0.2]; // position on the quad\n\n_jointDescription =\n[\n// Limits\n\t// Linear\n\t[], // Default is locked\n\n\t// Swing\n\t// [swing1 yaw, swing2 roll, springParams]\n\t[\n\t\trad 45, // yaw\n\t\t0 // roll\n\t],\n\t// Twist pitch\n\t// [twistLower, twistUpper, springParams]\n\t[rad -20, rad 20], // Default is locked\n\n// Drives\n\t[] // Default are none\n];\n\n_params = [\n\t\"6DOFJoint\",\n\t// From [pos,dir,up]\n\t[_parentPos, _parentPos vectorAdd [0, 1, 0], _parentPos vectorAdd [0, 0, 1]],\n\t// To [pos,dir,up]\n\t[_childPos, _childPos vectorAdd [0, 1, 0], _childPos vectorAdd [0, 0, 1]],\n\t// misc [collisions enabled]\n\t[false],\n\t_jointDescription\n];\n\n[vParent, towBar] attachChild _params;\n\n_parentPos = [0, -1, -0.2]; // Position on the quad\n_childPos = [0, 5, 0]; // Position on the hemtt\n\n_params = [\n\t\"6DOFJoint\",\n\t// From [pos,dir,up]\n\t[_parentPos, _parentPos vectorAdd [0, 1, 0], _parentPos vectorAdd[0, 0, 1]],\n\t// To [pos,dir,up]\n\t[_childPos, _childPos vectorAdd [0, 1, 0], _childPos vectorAdd [0, 0, 1]],\n\t// misc [collisions enabled]\n\t[false],\n\t_jointDescription\n];\n\n[towBar, vChild] attachChild _params;"]},{"text":"Attach a Quad (varname towbar) to a HEMTT (varName vParent) and another HEMTT (varName vChild) to the Quad.\nBut we rotate the axis so that Swing's are Pitch/Yaw and Twist is roll\n\n```sqf\n_parentPos = [0, -5, 0]; // position on the hemtt\n_childPos = [0, 1, -0.2]; // position on the quad\n\n_jointDescription =\n[\n// Limits\n    // Linear\n    [], // Default is locked\n\n    // Swing\n    // [swing1 pitch, swing2 yaw, springParams]\n    [\n        rad 20, // pitch\n        rad 45 // yaw\n    ],\n    // Twist roll\n    // [twistLower, twistUpper, springParams]\n    [], // Default is locked\n\n// Drives\n    [] // Default are none\n];\n\n_params = [\n    \"6DOFJoint\",\n    // From [pos,dir,up]\n    [_parentPos, _parentPos vectorAdd [0, 0, 1], _parentPos vectorAdd [1, 0, 0]], // Note how the up is pointing right and forward is pointing down, we are rotating the whole joint\n    // To [pos,dir,up]\n    [_childPos, _childPos vectorAdd [0, 0, 1], _childPos vectorAdd [1, 0, 0]],\n    // misc [collisions enabled]\n    [false],\n    _jointDescription\n];\n\n[vParent, towBar] attachChild _params;\n\n_parentPos = [0, -1, -0.2]; // Position on the quad\n_childPos = [0, 5, 0]; // Position on the hemtt\n\n_params = [\n    \"6DOFJoint\",\n    // From [pos,dir,up]\n    [_parentPos, _parentPos vectorAdd [0, 0, 1], _parentPos vectorAdd [1, 0, 0]],\n    // To [pos,dir,up]\n    [_childPos, _childPos vectorAdd [0, 0, 1], _childPos vectorAdd [1, 0, 0]],\n    // misc [collisions enabled]\n    [false],\n    _jointDescription\n];\n\n[towBar, vChild] attachChild _params;\n```","code":["_parentPos = [0, -5, 0]; // position on the hemtt\n_childPos = [0, 1, -0.2]; // position on the quad\n\n_jointDescription =\n[\n// Limits\n\t// Linear\n\t[], // Default is locked\n\n\t// Swing\n\t// [swing1 pitch, swing2 yaw, springParams]\n\t[\n\t\trad 20, // pitch\n\t\trad 45 // yaw\n\t],\n\t// Twist roll\n\t// [twistLower, twistUpper, springParams]\n\t[], // Default is locked\n\n// Drives\n\t[] // Default are none\n];\n\n_params = [\n\t\"6DOFJoint\",\n\t// From [pos,dir,up]\n\t[_parentPos, _parentPos vectorAdd [0, 0, 1], _parentPos vectorAdd [1, 0, 0]], // Note how the up is pointing right and forward is pointing down, we are rotating the whole joint\n\t// To [pos,dir,up]\n\t[_childPos, _childPos vectorAdd [0, 0, 1], _childPos vectorAdd [1, 0, 0]],\n\t// misc [collisions enabled]\n\t[false],\n\t_jointDescription\n];\n\n[vParent, towBar] attachChild _params;\n\n_parentPos = [0, -1, -0.2]; // Position on the quad\n_childPos = [0, 5, 0]; // Position on the hemtt\n\n_params = [\n\t\"6DOFJoint\",\n\t// From [pos,dir,up]\n\t[_parentPos, _parentPos vectorAdd [0, 0, 1], _parentPos vectorAdd [1, 0, 0]],\n\t// To [pos,dir,up]\n\t[_childPos, _childPos vectorAdd [0, 0, 1], _childPos vectorAdd [1, 0, 0]],\n\t// misc [collisions enabled]\n\t[false],\n\t_jointDescription\n];\n\n[towBar, vChild] attachChild _params;"]}],"multiplayer":"> [!IMPORTANT]\n> This command does NOT behave well in Multiplayer.","problems":null,"aliases":[],"see_also":["detachChild","setJointDrivePosition","setJointDriveOrientation","setJointDriveLinearVelocity","setJointDriveAngularVelocity","childAttached","parentAttached"],"notes":[],"categories":["Arma 3: New Scripting Commands","Arma 3: Scripting Commands","Command Group: PhysX","Introduced with Arma 3 version 2.22","Scripting Commands","Scripting Commands: Global Effect","WIP"]}