Search Unity

  1. Megacity Metro Demo now available. Download now.
    Dismiss Notice
  2. Unity support for visionOS is now available. Learn more in our blog post.
    Dismiss Notice

How would you build a Grappling Hook mechanic for Kinematic Rigidbody character? (3D)

Discussion in 'Physics' started by ml785, Jul 20, 2021.

  1. ml785

    ml785

    Joined:
    Dec 20, 2018
    Posts:
    119
    Hi,
    I am considering using a Kinematic Rigidbody for my character, but I am worried that a Grappling Hook mechanic will be very hard to implement for Kinematic.
    The common approach with (non-Kinematic) Rigidbodies is to attach a Spring Joint to the character.
    But Kinematic Rigidbodies wouldn't have natural physics-based movements from that.
    Does anyone know how to get started with creating believable Kinematic Rigidbody interactions regarding Grappling Hooks or similar "pendulum" mechanics like Rope Swing? (3D)

    For reference, the common Grappling Hook code is like this:
    Code (CSharp):
    1. using UnityEngine;
    2.  
    3. public class GrapplingGun : MonoBehaviour {
    4.  
    5.     private LineRenderer lr;
    6.     private Vector3 grapplePoint;
    7.     public LayerMask whatIsGrappleable;
    8.     public Transform gunTip, camera, player;
    9.     private float maxDistance = 100f;
    10.     private SpringJoint joint;
    11.  
    12.     void Awake() {
    13.         lr = GetComponent<LineRenderer>();
    14.     }
    15.  
    16.     void Update() {
    17.         if (Input.GetMouseButtonDown(0)) {
    18.             StartGrapple();
    19.         }
    20.         else if (Input.GetMouseButtonUp(0)) {
    21.             StopGrapple();
    22.         }
    23.     }
    24.  
    25.     //Called after Update
    26.     void LateUpdate() {
    27.         DrawRope();
    28.     }
    29.  
    30.     /// <summary>
    31.     /// Call whenever we want to start a grapple
    32.     /// </summary>
    33.     void StartGrapple() {
    34.         RaycastHit hit;
    35.         if (Physics.Raycast(camera.position, camera.forward, out hit, maxDistance, whatIsGrappleable)) {
    36.             grapplePoint = hit.point;
    37.             joint = player.gameObject.AddComponent<SpringJoint>();
    38.             joint.autoConfigureConnectedAnchor = false;
    39.             joint.connectedAnchor = grapplePoint;
    40.  
    41.             float distanceFromPoint = Vector3.Distance(player.position, grapplePoint);
    42.  
    43.             //The distance grapple will try to keep from grapple point.
    44.             joint.maxDistance = distanceFromPoint * 0.8f;
    45.             joint.minDistance = distanceFromPoint * 0.25f;
    46.  
    47.             //Adjust these values to fit your game.
    48.             joint.spring = 4.5f;
    49.             joint.damper = 7f;
    50.             joint.massScale = 4.5f;
    51.  
    52.             lr.positionCount = 2;
    53.             currentGrapplePosition = gunTip.position;
    54.         }
    55.     }
    56.  
    57.  
    58.     /// <summary>
    59.     /// Call whenever we want to stop a grapple
    60.     /// </summary>
    61.     void StopGrapple() {
    62.         lr.positionCount = 0;
    63.         Destroy(joint);
    64.     }
    65.  
    66.     private Vector3 currentGrapplePosition;
    67.  
    68.     void DrawRope() {
    69.         //If not grappling, don't draw rope
    70.         if (!joint) return;
    71.  
    72.         currentGrapplePosition = Vector3.Lerp(currentGrapplePosition, grapplePoint, Time.deltaTime * 8f);
    73.      
    74.         lr.SetPosition(0, gunTip.position);
    75.         lr.SetPosition(1, currentGrapplePosition);
    76.     }
    77.  
    78.     public bool IsGrappling() {
    79.         return joint != null;
    80.     }
    81.  
    82.     public Vector3 GetGrapplePoint() {
    83.         return grapplePoint;
    84.     }
    85. }
    Thanks for any help here.