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

Question Problems with my Grappling Hook

Discussion in 'Scripting' started by Maaarw, Jun 4, 2023.

  1. Maaarw

    Maaarw

    Joined:
    May 21, 2023
    Posts:
    2
    Hey,

    I just finished a grappling hook for my game, but very quickly realized that it quickly messes up my player movement.

    When I start the game and look forward while doing "A" for running left, a force automatically pulls me to the right.

    When I delete the grappling hook, my movement works normally again.

    Can anyone help me with this?


    Grappling:

    using System.Collections;
    using System.Collections.Generic;
    using UnityEngine;

    public class Garppling : MonoBehaviour
    {

    private LineRenderer lr;
    private Vector3 grapplePoint;
    public LayerMask whatIsGrappleable;
    public Transform gunTip, camera, player;
    private float maxDistance = 25f;
    private SpringJoint joint;

    void Awake()
    {
    lr = GetComponent<LineRenderer>();
    }

    void Update()
    {
    if (Input.GetMouseButtonDown(1))
    {
    StartGrapple();
    }
    else if (Input.GetMouseButtonUp(1))
    {
    StopGrapple();
    }
    }

    //Called after Update
    void LateUpdate()
    {
    DrawRope();
    }

    /// <summary>
    /// Call whenever we want to start a grapple
    /// </summary>
    void StartGrapple()
    {
    RaycastHit hit;
    if (Physics.Raycast(camera.position, camera.forward, out hit, maxDistance, whatIsGrappleable))
    {
    grapplePoint = hit.point;
    joint = player.gameObject.AddComponent<SpringJoint>();
    joint.autoConfigureConnectedAnchor = false;
    joint.connectedAnchor = grapplePoint;

    float distanceFromPoint = Vector3.Distance(player.position, grapplePoint);

    //The distance grapple will try to keep from grapple point.
    joint.maxDistance = distanceFromPoint * 0.8f;
    joint.minDistance = distanceFromPoint * 0.25f;

    //Adjust these values to fit your game.
    joint.spring = 4.5f;
    joint.damper = 7f;
    joint.massScale = 4.5f;

    lr.positionCount = 2;
    currentGrapplePosition = gunTip.position;
    }
    }


    /// <summary>
    /// Call whenever we want to stop a grapple
    /// </summary>
    void StopGrapple()
    {
    lr.positionCount = 0;
    Destroy(joint);
    }

    private Vector3 currentGrapplePosition;

    void DrawRope()
    {
    //If not grappling, don't draw rope
    if (!joint) return;

    currentGrapplePosition = Vector3.Lerp(currentGrapplePosition, grapplePoint, Time.deltaTime * 8f);

    lr.SetPosition(0, gunTip.position);
    lr.SetPosition(1, currentGrapplePosition);
    }

    public bool IsGrappling()
    {
    return joint != null;
    }

    public Vector3 GetGrapplePoint()
    {
    return grapplePoint;
    }
    }


    Movement:

    using System.Collections;
    using System.Collections.Generic;
    using UnityEngine;

    public class PlayerMovement : MonoBehaviour
    {
    [Header("Movement")]
    public float moveSpeed;


    public float groundDrag;

    public float jumpForce;
    public float jumpCooldown;
    public float airMultiplier;
    bool readyToJump;

    [HideInInspector] public float walkSpeed;
    [HideInInspector] public float sprintSpeed;

    [Header("Keybinds")]
    public KeyCode jumpKey = KeyCode.Space;

    [Header("Ground Check")]
    public float playerHeight;
    public LayerMask whatIsGround;
    bool grounded;

    public Transform orientation;

    float horizontalInput;
    float verticalInput;

    Vector3 moveDirection;

    Rigidbody rb;





    private void Start()
    {
    rb = GetComponent<Rigidbody>();
    rb.freezeRotation = true;

    readyToJump = true;
    }

    private void Update()
    {
    // ground check
    grounded = Physics.Raycast(transform.position, Vector3.down, playerHeight * 0.5f, whatIsGround);

    MyInput();
    SpeedControl();

    // handle drag
    if (grounded)
    rb.drag = groundDrag;
    else
    rb.drag = 0;
    }

    private void FixedUpdate()
    {
    MovePlayer();
    }

    private void MyInput()
    {
    horizontalInput = Input.GetAxisRaw("Horizontal");
    verticalInput = Input.GetAxisRaw("Vertical");

    // when to jump
    if (Input.GetKey(jumpKey) && readyToJump && grounded)
    {
    readyToJump = false;

    Jump();

    Invoke(nameof(ResetJump), jumpCooldown);
    }
    }

    private void MovePlayer()
    {
    // calculate movement direction
    moveDirection = orientation.forward * verticalInput + orientation.right * horizontalInput;

    // on ground
    if (grounded)
    rb.AddForce(moveDirection.normalized * moveSpeed * 10f, ForceMode.Force);

    // in air
    else if (!grounded)
    rb.AddForce(moveDirection.normalized * moveSpeed * 10f * airMultiplier, ForceMode.Force);
    }

    private void SpeedControl()
    {
    Vector3 flatVel = new Vector3(rb.velocity.x, 0f, rb.velocity.z);

    // limit velocity if needed
    if (flatVel.magnitude > moveSpeed)
    {
    Vector3 limitedVel = flatVel.normalized * moveSpeed;
    rb.velocity = new Vector3(limitedVel.x, rb.velocity.y, limitedVel.z);
    }
    }

    private void Jump()
    {
    // reset y velocity
    rb.velocity = new Vector3(rb.velocity.x, 0f, rb.velocity.z);

    rb.AddForce(transform.up * jumpForce, ForceMode.Impulse);
    }
    private void ResetJump()
    {
    readyToJump = true;
    }


    }