Search code examples
unity-game-enginemultiplayerphoton-pun

Line Renderer not visible to other Players | Unity PUN 2


I'm trying to sync a Line Renderer which is given out by a Grappling Gun and it doesn't seem to be working. I've seen other forums, answers, etc but I'm just stuck with this for the past 2 days.

Here is the code which I'm using:

//The Script used to draw the Grappling Rope!

using System.Collections;
using System.Collections.Generic;
using Photon.Pun;
using UnityEngine;

public class GrapplingRope : MonoBehaviour
{
    //References
    [Header("References")]
    [SerializeField] private GrapplingGun grapplingGun;
    [SerializeField] private AnimationCurve affectCurve;
    [SerializeField] private PhotonView photonView;
    
    [Header("Settings")]
    [SerializeField] private int quality;
    [SerializeField] private float damper;
    [SerializeField] private float strength;
    [SerializeField] private float velocity;
    [SerializeField] private float waveCount;
    [SerializeField] private float waveHeight;

    private Spring spring;
    private LineRenderer lr;
    private Vector3 currentGrapplePosition;

    private bool calledOnlyOnce = false;
    
    [HideInInspector] public bool viewIsMine;

    private void Awake()
    {
        if (photonView.IsMine)
        {
            lr = GetComponent<LineRenderer>(); //Get the Line Renderer component
            spring = new Spring(); //Create the Spring component
            spring.SetTarget(0); //Set the Spring target to 0   
        }
    }

    //Method called after Update Method
    private void LateUpdate()
    {
        if (viewIsMine)
        {
            photonView.RPC("DrawRope", RpcTarget.AllBuffered);
        }
    }
    
    [PunRPC]
    private void DrawRope()
    {
        if (!calledOnlyOnce)
        {
            spring = new Spring(); //Create the Spring component
            spring.SetTarget(0); //Set the Spring target to 0
            lr = GetComponent<LineRenderer>(); //Get the Line Renderer component

            calledOnlyOnce = true;
        }

        if (!grapplingGun.IsGrappling()) //If not "grappling"
        {
            currentGrapplePosition = grapplingGun.gunTip.position; //Set the grappling position
            spring.Reset(); //Set the spring's velocity and value to 0

            if (lr.positionCount > 0) //If line renderer's position is greater than 0
            {
                lr.positionCount = 0; //Set the  line renderer's position to 0
            }
            return; //Return
        }

        if (lr.positionCount == 0) //If line renderer's position is equal to 0
        {
            spring.SetVelocity(velocity); //Set the velocity value
            lr.positionCount = quality + 1; //Set the position count value   
        }

        
        spring.SetDamper(damper); //Set the damper value
        spring.SetStrength(strength); //Set the strength value
        spring.Update(Time.deltaTime); //Update the spring according to the time
        
        var grapplePoint = grapplingGun.GetGrapplePoint();
        var gunTipPosition = grapplingGun.gunTip.position;
        var up = Quaternion.LookRotation((grapplePoint - gunTipPosition).normalized) * Vector3.up;

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

        for (var i = 0; i < quality + 1; i++)
        {
            var delta = i / (float)quality;
            var offset = up * waveHeight * Mathf.Sin(delta * waveCount * Mathf.PI) * spring.Value *
                         affectCurve.Evaluate(delta);

            lr.SetPosition(i, Vector3.Lerp(gunTipPosition, currentGrapplePosition, delta) + offset);
        }
    }
}

And here is a video explaining the problem: https://www.youtube.com/watch?v=ljC0-u5Jz1I

I think I'm missing something very basic here so any help would be appreciated!


Solution

  • If I am not mistaken, a grappling gun would shoot just once. When it does, the trajectory is usually clear and immutable, so the path that a line renderer would cover, should also be defined?! Essentially, you want to only sync from where to where someone shot, then use the line renderer to cover the distance?! That can be sent in one update. Everyone who receives the "shot" RPC can then animate the flight of the hook and draw the line.

    Sending an update per frame can easily become too much for most network connections and will cause loss and delays in most cases. It is less detailed than sending fewer updates or just one that defines the line.