- Home /
Line Renderers tied to ball keep teleporting/glitching after instantiate
Hi, I'm trying to create a catapult simulating type game where I attach 2 spring joints to a ball and attach line renderers to two cylinders either side of it, I have made a script that upon the release of a ball spawns another identical ball prefab and reattaches the line renderers to the new ball. One the first throw of the ball this works fine however once a new one is loaded in the linerenderers keep switching between two positions (sometimes it will switch between the intended position, and then a fair bit in front of the ball). I have no idea why any of this is happening so any help would be greatly appreciated. My script is attached below. Thanks.
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class BallHandler : MonoBehaviour
{
public GameObject catapultLeft;
public GameObject catapultRight;
public GameObject ballPrefab;
private Vector3 ballSpawnPos;
private int ballCounter = 0;
// Start is called before the first frame update
void Start()
{
ballSpawnPos = GameObject.Find("Sphere").transform.position;
}
// Update is called once per frame
void Update()
{
if (GameObject.Find("Sphere").GetComponent<SwipeDetect>().newBall)
{
GameObject.Find("Sphere").name = "thrown" + ballCounter.ToString();
GameObject newBall = Instantiate(ballPrefab, ballSpawnPos, Quaternion.identity);
newBall.name = "Sphere";
newBall.GetComponent<SwipeDetect>().catapultLeft = catapultLeft;
newBall.GetComponent<SwipeDetect>().catapultRight = catapultRight;
catapultLeft.GetComponent<LineRenderer>().enabled = true;
catapultRight.GetComponent<LineRenderer>().enabled = true;
Destroy(GameObject.Find("thrown" + ballCounter.ToString()).GetComponent<SwipeDetect>());
ballCounter++;
}
}
}
Answer by unity_ek98vnTRplGj8Q · Feb 12, 2020 at 05:42 AM
I'm guna be real with you man, seeing so many GameObject.Find()'s is really scaring me. Not only is it not good practice and very inefficient, but I'll bet its contributing to your issue (I know you have the logic in there to only ever have one object named sphere but still it scares me). I highly recommend keeping a hard reference to the object you are trying to use for the line renderer rather than re-finding it every frame. Also if you want me to list the (hundreds) of reasons why GameObject.Find is a bad function to use then I can, but for now take my word for it that you should really never use it except for super quick prototyping.
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class BallHandler : MonoBehaviour
{
public GameObject catapultLeft;
public GameObject catapultRight;
public GameObject ballPrefab;
private Vector3 ballSpawnPos;
private int ballCounter = 0;
public GameObject currentBall;
// Start is called before the first frame update
void Start()
{
//This is the only call of GameObject.Find() that could maybe be ok
currentBall = GameObject.Find("Sphere");
ballSpawnPos = currentBall.transform.position;
}
// Update is called once per frame
void Update()
{
if (currentBall.GetComponent<SwipeDetect>().newBall)
{
Destroy(currentBall.GetComponent<SwipeDetect>());
GameObject newBall = Instantiate(ballPrefab, ballSpawnPos, Quaternion.identity);
newBall.GetComponent<SwipeDetect>().catapultLeft = catapultLeft;
newBall.GetComponent<SwipeDetect>().catapultRight = catapultRight;
catapultLeft.GetComponent<LineRenderer>().enabled = true;
catapultRight.GetComponent<LineRenderer>().enabled = true;
currentBall = newBall;
ballCounter++;
}
}
}
Do the same sorta deal in the script that sets the line renderer position (get a reference to this script and look at the currentBall variable). If this doesn't fix your issue then we will have to dig into more of your code.
Also as a side note, you can run into performance problems by calling GetComponent() in your update method. Try only calling it once when you spawn an object or enable a script, and saving the result in a private variable. This is less of an issue than GameObject.Find though...
Hi, thanks for your help so far. I took your suggestion and modified my scripts to reference the currentBall variable in my main script however the same behaviour still appears to be occurring. This is my main script now:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class BallHandler : $$anonymous$$onoBehaviour
{
public GameObject catapultLeft;
public GameObject catapultRight;
public GameObject ballPrefab;
private Vector3 ballSpawnPos;
private int ballCounter = 0;
public GameObject currentBall;
// Start is called before the first frame update
void Start()
{
currentBall = GameObject.Find("Sphere");
ballSpawnPos = currentBall.transform.position;
}
// Update is called once per frame
void Update()
{
if (currentBall.GetComponent<SwipeDetect>().newBall)
{
Destroy(currentBall.GetComponent<SwipeDetect>());
//GameObject.Find("Sphere").name = "thrown" + ballCounter.ToString();
GameObject newBall = Instantiate(ballPrefab, ballSpawnPos, Quaternion.identity);
//newBall.name = "Sphere";
newBall.GetComponent<SwipeDetect>().catapultLeft = catapultLeft;
newBall.GetComponent<SwipeDetect>().catapultRight = catapultRight;
catapultLeft.GetComponent<LineRenderer>().enabled = true;
catapultRight.GetComponent<LineRenderer>().enabled = true;
//Destroy(GameObject.Find("thrown" + ballCounter.ToString()).GetComponent<SwipeDetect>());
currentBall = newBall;
ballCounter++;
}
}
}
And the below are my lineRenderer scripts attached to each side of the catapult (the other is exactly the same but has a slightly different x position):
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class DrawLine1 : $$anonymous$$onoBehaviour
{
private LineRenderer lr;
public $$anonymous$$aterial colour;
private BallHandler ballHandler;
// Start is called before the first frame update
public void Start()
{
ballHandler = GameObject.Find("Runtime").GetComponent<BallHandler>();
lr = GetComponent<LineRenderer>();
lr.enabled = false;
lr.startWidth = 0.02F;
lr.endWidth = 0.02F;
lr.positionCount = 2;
lr.SetPosition(0, new Vector3(ballHandler.currentBall.transform.position.x - 0.5F, ballHandler.currentBall.transform.position.y - 0.12F, ballHandler.currentBall.transform.position.z));
lr.material = colour;
lr.enabled = true;
}
// Update is called once per frame
void Update()
{
lr.SetPosition(1, ballHandler.currentBall.transform.position);
}
}
Any ideas?
Hmmmm no the behavior is definitely spooky. Can you maybe attach a video of the glitch?
Here is an attached video of the glitch: https://www.dropbox.com/s/oooeu08i5e074fy/Unity%202018.4.7f1%20Personal%20-%20SampleScene.unity%20-%20Catapult%20-%20PC%2C%20$$anonymous$$ac%20%26%20Linux%20Standalone%20_DX11_%202020-02-15%2012-16-08.mp4?dl=0
There is also one more script on in the scene that works on pulling back the ball depending on swipe position, which I didn't think would be the problem at first but it now might be hinting towards that, if so I have attached that one last script here: https://pastebin.com/GANvA23G
That's everything in my scene then so it must be something based on one of those scripts (on the video you can see a projectiletrail script and gameobject but those are inactive at the moment and have no function).
Your answer
Follow this Question
Related Questions
Glitching Line Renderers upon tying to new game object 1 Answer
Multiple Buildings Placement 1 Answer
Instantiating a string of prefab lights along a line renderer? 0 Answers
Instantiate and add Rigidbody force 3 Answers
LineRenderer not instantiating on iOS or Xcode, Works fine in editor and Unity Remote 0 Answers