- Home /
RayCast, origin not updating fast enough
I made a laser system for the guns in my game, it works fine but when I move the character it seems the origin of the RayCast its not updating fast enough and its not moving with the gun but a bit slower, here its my code also I included some pictures of the problem (in the second picture I meant to write "Laser not moving with the gun"):
I have been testing a number of solutions including adding the script directly to the gun so I narrowed it down to RayCast Origin.
Im really worried about this, if I cant make this be accurate the bullets are gonna be really inaccurate, also it looks very bad, laser sigths are suppose to be really reliable and accurate.
using UnityEngine;
using System.Collections;
[AddComponentMenu("Rayco's scripts/Laser")]
public class laser : MonoBehaviour {
public GameObject weapon;
public int LaserLength;
public Vector3 RotationOffset;
public Vector3 PositionOffset;
public Material LaserMaterial;
public Color LaserColor;
public Color LaserEndColor;
public float LaserStartWidth;
public float LaserEndWidth;
Ray ray;
void Start () {
LineRenderer lineRenderer = gameObject.AddComponent<LineRenderer>();
transform.position = weapon.transform.position;
transform.parent = weapon.transform;
transform.localEulerAngles = RotationOffset;
transform.localPosition = PositionOffset;
//LineRenderer options
lineRenderer.material = LaserMaterial;
lineRenderer.SetColors(LaserColor,LaserEndColor);
lineRenderer.SetVertexCount(2);
lineRenderer.SetWidth(LaserStartWidth,LaserEndWidth);
lineRenderer.useWorldSpace = true;
}
void Update() {
//LineRenderer
LineRenderer lineRenderer = GetComponent<LineRenderer>();
//Raycast stuff
ray.origin = transform.position;
ray.direction = transform.forward;
RaycastHit hit;
lineRenderer.SetPosition(0,ray.origin);
if (Physics.Raycast (ray, out hit, LaserLength)){
//Debug.DrawLine draws a line on game view, I have it for testing pourposes, you may delete any reference to it
Debug.DrawLine(ray.origin, hit.point, Color.red);
lineRenderer.SetPosition(1,hit.point);
}
else{
Debug.DrawLine(ray.origin,ray.GetPoint(LaserLength), Color.red);
lineRenderer.SetPosition (1,ray.GetPoint(LaserLength));
}
}
}
Not that it might solve it, but you could move that GetComponent to Start so you don't have to call that every Update
You cant do that. If you do that the things in the update dont know what "lineRenderer" is. Also if you have AddComponent and GetComponent in the same function the script doesnt even compile.
Are you saying that if you moved lineRenderer outside these functions (make it global to this script), that it won't work, that you can't remove the GetComponent in Update? That's odd.
Actually, I think You cant make it global, I tried and gave me error everytime, you can have "Public LineRenderer" and add a gameobject with LineRenderer there though.
Answer by Bunny83 · Jan 15, 2013 at 01:19 AM
Since a LineRenderer is a component attached to a gameobject, why not just using local space coordinates?
LineRenderer m_LineRenderer;
void Start ()
{
// ...
m_LineRenderer = GetComponent<LineRenderer>();
// ...
m_LineRenderer.SetVertexCount(2);
m_LineRenderer.useWorldSpace = false; // use local space
m_LineRenderer.SetPosition(0,Vector3.zero);
}
void Update()
{
// ...
if (Physics.Raycast (ray, out hit, LaserLength))
{
m_LineRenderer.SetPosition(1,new Vector3(0,0,hit.distance));
}
}
hit.distance works because your LineRenderer objects forward direction points in the same direction as your ray.
As alternative you can use InverseTransformPoint like this:
if (Physics.Raycast (ray, out hit, LaserLength))
{
var P = m_LineRenderer.transform.InverseTransformPoint(hit.point);
m_LineRenderer.SetPosition(1, P);
}
oops I found a different problem now. Now the laser doesnt stop on RayCast hit.
void Update() { //LineRenderer LineRenderer lineRenderer = GetComponent(); //Raycast stuff ray.direction = transform.forward; RaycastHit hit; if (Physics.Raycast (ray, out hit, LaserLength)){ lineRenderer.SetPosition (1,new Vector3 (0,0,hit.distance)); } else{ lineRenderer.SetPosition (1,new Vector3 (0,0,LaserLength)); } }
}
Answer by Chronos-L · Jan 15, 2013 at 01:50 AM
I have the same problem before, it is with a 2D marker tracking a 3D scene object. I came out with 2 different solutions for my problem.
How about using LateUpdate()
instead of Update()
in your laser script? It is possible that the Update()
from your laser script is run before the Update()
of your movement script. Hence there is a slight inaccuracy everytime you move and yet, everything looks fine when you are not moving.
Another possible solution is to redraw the laser in your movement script:
public class laser : MonoBehaviour {
...
void Start() {
...
}
void Draw() {
//LineRenderer
LineRenderer lineRenderer = GetComponent<LineRenderer>();
//Raycast stuff
ray.origin = transform.position;
ray.direction = transform.forward;
...
}
}
Then in your movement script:
public class movement : MonoBehavior {
public Laser laser;
...
...
void movementfunction() {
...
//Call the Draw() at the end of your movement
laser.Draw();
}
}
By following any of these 2 method, the laser will always be drawn after the movement is calculated at each frame of your game. Hopes that this will help you.
I tried LateUpdate before posting here, didnt work. But anyways my problem its fixed, Bunny83's solution worked for me. Thanks for trying to help me.
Your answer
Follow this Question
Related Questions
Get raycast direction from weapon 1 Answer
Creating a Ray Gun 1 Answer
3D Space Shooter Firing Projectiles 0 Answers
How should i add raycast to multiple game objects??? 0 Answers
Can someone explain to me why this raycast doesn't fire straight? 1 Answer