Line Renderer not actually attaching to GameObject correctly

My game has 2 grapplers, one for left and right, and for some reason, and the line renderer won’t ever actually attach to the game object. It’s always floating a little bit to the side of the gameobject, is there any way to fix this?
Here’s the code:

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
using UnityEngine.InputSystem;

public class Grapple : MonoBehaviour
{
    [Header("Keybinds")]
    public string direction = "";
    public InputActionReference attackKeybind;

    [Header("Grappling")]
    public float maxDistance = 100f;
    public bool grappling = false;
    public Transform grappleOrigin;
    public LayerMask whatIsGrappleable;
    public GameObject player;
    public GameObject GrapplePoint;
    public float grappleForce = 38f;
    private LineRenderer lr;
    private Vector3 grapplePoint;
    private Vector3 currentGrapplePosition;

    // public AudioClip grappleSound;
    // public AudioClip hitSound;


    [Header("Camera")]
    public Transform playerCam;

    [Header("Other")]
    Animator animator;

    public const string IDLE = "Idle";
    public const string GRAPPLE = "Grapple";

    public const string IDLER = "IdleR";
    public const string GRAPPLER = "GrappleR";

    string currentAnimationState;

    private void OnEnable()
    {
        attackKeybind.action.Enable();
    }

    private void OnDisable()
    {
        attackKeybind.action.Disable();
    }

    void Awake()
    {
        animator = GetComponentInChildren<Animator>();
        lr = GetComponent<LineRenderer>();
        lr.positionCount = 0;
    }

    // Update is called once per frame
    void Update()
    {
        if (attackKeybind.action.IsPressed())
        {
            RaycastHit hit;
            if (Physics.Raycast(playerCam.position, playerCam.forward, out hit, maxDistance, whatIsGrappleable))
            {
                if (!grappling)
                {
                    GameObject copyGrapplePoint = Instantiate(GrapplePoint, hit.point, Quaternion.identity);
                    copyGrapplePoint.name = "newGrapplePoint" + direction;
                }
                grappling = true;
                grapplePoint = hit.point;
                Rigidbody rb = player.GetComponent<Rigidbody>();
                Vector3 directionToGrapplePoint = GameObject.Find("newGrapplePoint" + direction).transform.position - transform.position;
                rb.AddForce(directionToGrapplePoint.normalized * grappleForce, ForceMode.Impulse);
            }
        }
        else if (attackKeybind.action.WasReleasedThisFrame())
        {
            StopGrapple();
        }

        SetAnimations();
    }

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

    public void ChangeAnimationState(string newState)
    {
        if (currentAnimationState == newState) return;

        currentAnimationState = newState;
        animator.CrossFadeInFixedTime(currentAnimationState, 0.2f);
    }

    void SetAnimations()
    {
        if (!grappling)
        {
            if (direction == "Left")
            {
                ChangeAnimationState(IDLE);
            }
            else
            {
                ChangeAnimationState(IDLER);
            }
        }
        else
            if (direction == "Left")
        {
            ChangeAnimationState(GRAPPLE);
        }
        else
        {
            ChangeAnimationState(GRAPPLER);
        }
    }

    void StopGrapple()
    {
        Destroy(GameObject.Find("newGrapplePoint" + direction));
        grappling = false;
        lr.positionCount = 0;
    }

    void DrawRope()
    {
        if (!grappling) return;

        lr.positionCount = 2;

        lr.SetPosition(0, grappleOrigin.position);
        lr.SetPosition(1, GameObject.Find("newGrapplePoint" + direction).transform.position);
    }
}

This is my first time using the site, so please correct me if I’m using this incorrectly.

Make sure your line renderer is set to Use World Space, OR make sure the Vector3’s you are passing in are accounting for local position space.

|

|

Additionally, while not related to your question, I see you are doing quite a few GameObject.Find() calls. These are notoriously expensive and I would definitely recommended caching as much as possible to avoid these. It looks like you can cache the New Grapple Point object when instantiating it to avoid the costly Find calls, and just use the cached reference.

Hope this helps and may the odds be ever in your favor!

-Joegre

Thanks for the tip, and I already switched to caching the New Grapple Point object. Though, it seems the main problem still hasn’t been solved. I checked the line renderer and I have it set to Use World Space, and most of the time the line connects fine, but as shown in this image, it seems to sometimes float away from the object.


I must’ve not explained well in the initial question, my bad. I’m pretty bad at communication.

Can you post the updated code?

Of course! Here’s the updated code:

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
using UnityEngine.InputSystem;

public class Grapple : MonoBehaviour
{
    [Header("Keybinds")]
    public string direction = "";
    public InputActionReference attackKeybind;

    [Header("Grappling")]
    public float maxDistance = 100f;
    public bool grappling = false;
    public Transform grappleOrigin;
    public LayerMask whatIsGrappleable;
    public GameObject player;
    public GameObject GrapplePoint;
    public float grappleForce = 38f;
    private LineRenderer lr;
    private Vector3 grapplePoint;
    private Vector3 currentGrapplePosition;
    private GameObject newGrapplePoint;

    // public AudioClip grappleSound;
    // public AudioClip hitSound;


    [Header("Camera")]
    public Transform playerCam;

    [Header("Other")]
    Animator animator;

    public const string IDLE = "Idle";
    public const string GRAPPLE = "Grapple";

    public const string IDLER = "IdleR";
    public const string GRAPPLER = "GrappleR";

    string currentAnimationState;

    private void OnEnable()
    {
        attackKeybind.action.Enable();
    }

    private void OnDisable()
    {
        attackKeybind.action.Disable();
    }

    void Awake()
    {
        animator = GetComponentInChildren<Animator>();
        lr = GetComponent<LineRenderer>();
        lr.positionCount = 0;
    }

    // Update is called once per frame
    void Update()
    {
        if (attackKeybind.action.IsPressed())
        {
            RaycastHit hit;
            if (Physics.Raycast(playerCam.position, playerCam.forward, out hit, maxDistance, whatIsGrappleable))
            {
                if (!grappling)
                {
                    newGrapplePoint = Instantiate(GrapplePoint, hit.point, Quaternion.identity);
                    newGrapplePoint.name = "newGrapplePoint" + direction;
                }
                grappling = true;
                grapplePoint = hit.point;
                Rigidbody rb = player.GetComponent<Rigidbody>();
                Vector3 directionToGrapplePoint = newGrapplePoint.transform.position - transform.position;
                rb.AddForce(directionToGrapplePoint.normalized * grappleForce, ForceMode.Impulse);
            }
        }
        else if (attackKeybind.action.WasReleasedThisFrame())
        {
            StopGrapple();
        }

        SetAnimations();
    }

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

    public void ChangeAnimationState(string newState)
    {
        if (currentAnimationState == newState) return;

        currentAnimationState = newState;
        animator.CrossFadeInFixedTime(currentAnimationState, 0.2f);
    }

    void SetAnimations()
    {
        if (!grappling)
        {
            if (direction == "Left")
            {
                ChangeAnimationState(IDLE);
            }
            else
            {
                ChangeAnimationState(IDLER);
            }
        }
        else
            if (direction == "Left")
            {
                ChangeAnimationState(GRAPPLE);
            }
            else
            {
                ChangeAnimationState(GRAPPLER);
            }
    }

    void StopGrapple()
    {
        Destroy(newGrapplePoint);
        grappling = false;
        lr.positionCount = 0;
    }

    void DrawRope()
    {
        if (!grappling) return;

        lr.positionCount = 2;

        lr.SetPosition(0, grappleOrigin.position);
        lr.SetPosition(1, newGrapplePoint.transform.position);
    }
}

Nevermind I seemed to fix it. While making the rope look better, it put it on a different game object so it wouldn’t display over everything and that seemed to fix it. For those wondering, the linerenderer was being rendered on the grappler, which is on a camera overlay to make sure it won’t clip through walls. So it seemed that putting on something not on that overlay fixed it :>
Thanks for all the help though!