- Home /
I need help with GL drawlines in unity
I have completed my whole project but after I built it I realized that Debug.Drawline
doesn't show in the built project. I tried to rewrite the part of the code that printed the lines but I couldn't figure out how to use Gizmos
and GL
.
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class OrbitPathFinder : MonoBehaviour
{
public int numSteps = 1000;
public float timeStep = 0.1f;
public float gravitationalConstant;
public bool relativeToBody;
public GameObject centralBody;
private GameObject[] bodies;
private bool gameOn = false;
public Material mat;
void Awake()
{
//DrawLineGL.CreateLinesGL();
}
void Update()
{
if(Input.GetKeyDown("space"))
{
gameOn = true;
}
if(gameOn)
{
HideOrbits();
}
else
{
DrawOrbits();
}
}
void DrawOrbits()
{
bodies = GameObject.FindGameObjectsWithTag("Body");
var virtualBodies = new VirtualBody[bodies.Length];
var drawPoints = new Vector3[bodies.Length][];
int referenceFrameIndex = 0;
Vector3 referenceBodyInitialPosition = Vector3.zero;
for (int i = 0;i < virtualBodies.Length;i++)
{
virtualBodies[i] = new VirtualBody (bodies[i]);
drawPoints[i] = new Vector3[numSteps];
if (bodies[i] == centralBody && relativeToBody) {
referenceFrameIndex = i;
referenceBodyInitialPosition = virtualBodies[i].position;
}
}
for (int step = 0; step < numSteps; step++) { //for each step simulate the virtual bodies
Vector3 referenceBodyPosition = (relativeToBody) ? virtualBodies[referenceFrameIndex].position : Vector3.zero;//the position of the reference body in every step
// Update velocities
for (int i = 0; i < virtualBodies.Length; i++) { //for each virtual body
virtualBodies[i].velocity += CalculateAcceleration (i, virtualBodies) * timeStep; //finds velocity of body at location
}
// Update positions
for (int i = 0; i < virtualBodies.Length; i++) { //for each virtual object
Vector3 newPos = virtualBodies[i].position + virtualBodies[i].velocity * timeStep; //new position is equal to the position and velocity times the time step
virtualBodies[i].position = newPos; //the virtual bodies position is then updated to the new position
if (relativeToBody) { //if there is a central body
var referenceFrameOffset = referenceBodyPosition - referenceBodyInitialPosition;// the offset of the reference frame is the new position - initialposition
newPos -= referenceFrameOffset; //the offset is then subtracted from the new position
}
if (relativeToBody && i == referenceFrameIndex) { //if relative to body and the reference frame is the current index
newPos = referenceBodyInitialPosition; //then the position will be the initalposition
}
drawPoints[i][step] = newPos; //The point where the line will be drawn has another value added
}
} |
//WHERE THE PROBLEM IS \/
Shader shader = Shader.Find("Hidden/Internal-Colored");
mat = new Material(shader);
mat.hideFlags = HideFlags.HideAndDontSave;
// Turn on alpha blending
mat.SetInt("_SrcBlend", (int)UnityEngine.Rendering.BlendMode.SrcAlpha);
mat.SetInt("_DstBlend", (int)UnityEngine.Rendering.BlendMode.OneMinusSrcAlpha);
// Turn backface culling off
mat.SetInt("_Cull", (int)UnityEngine.Rendering.CullMode.Off);
// Turn off depth writes
mat.SetInt("_ZWrite", 0);
mat.SetPass(0);
GL.PushMatrix();
GL.LoadOrtho();
for (int bodyIndex = 0; bodyIndex < virtualBodies.Length; bodyIndex++)
{
var pathColour = bodies[bodyIndex].gameObject.GetComponent<TrailRenderer> ().sharedMaterial.color;
//sets the path to the colour of the object
GL.Begin(GL.LINES);
for (int i = 0; i < drawPoints[bodyIndex].Length - 1; i++) {
GL.Vertex3(drawPoints[bodyIndex][i].x, drawPoints[bodyIndex][i].y, drawPoints[bodyIndex][i].z);
var lineRenderer = bodies[bodyIndex].gameObject.GetComponentInChildren<LineRenderer> ();
if (lineRenderer) {
lineRenderer.enabled = false; //disables the linerenderer in the child object of the planet
}
}
GL.End();
GL.PopMatrix();
}
}
void HideOrbits()
{
for (int bodyIndex = 0; bodyIndex < bodies.Length; bodyIndex++) { //for each body
var lineRenderer = bodies[bodyIndex].gameObject.GetComponentInChildren<LineRenderer> ();
lineRenderer.positionCount = 0; //sets the amount of positions to 0
}
}
Vector3 CalculateAcceleration (int i, VirtualBody[] virtualBodies) {
Vector3 acceleration = Vector3.zero;//acceleration = 0
for (int j = 0; j < virtualBodies.Length; j++) {//foreach virtual body
if (i == j) { //if the index of the virtual body is the same as the real objects then continue
continue;// /\
} // |
Vector3 forceDir = (virtualBodies[j].position - virtualBodies[i].position).normalized;
float sqrDst = (virtualBodies[j].position - virtualBodies[i].position).sqrMagnitude;
acceleration += forceDir * gravitationalConstant * virtualBodies[j].mass / sqrDst;
} //find the acceleration of the vitual object at that point using gravity formula
return acceleration;//return the value of the acceleration
}
class VirtualBody
{
public Vector3 position;
public Vector3 velocity;
public float mass;
public VirtualBody(GameObject g)
{
position = g.transform.position;
velocity = g.GetComponent<gravity>().startVelocity;
mass = g.GetComponent<Rigidbody2D>().mass;
}
}
}
Default reference space for Gizmos
is world space. GL
uses whatever space you tell it to. This is where your mistake lies - you're trying draw lines in "view space" ( GL.LoadOrtho();
) while providing world coordinates.
Answer by Bunny83 · May 25, 2021 at 11:44 PM
Most Gizmo stuff only works inside the Editor. The GL class does work at runtime, however most stuff in the GL class are immediate mode commands. So you can not use it inside Update. Update runs way before rendering even starts. The first thing that happens when rendering actually starts is that the screen is cleared. So anything drawn before the rendering stage is pointless / generally doesn't work.
So you have to use a rendering callback. Something like: OnRenderObject. Or on a script attached to the camera you could use OnPostRender or OnRenderImage (though the last one is specifically for image effects).
Alternatively you can also use OnGUI or a Coroutine that uses WaitForEndOfFrame. The Render event in OnGUI is one of the latest rendering events. WaitForEndOfFrame is literally the last one. WaitForEndOfFrame could be too late for certain operations. If you just want to render something as if it's part of the scene, use OnRenderObject. For screen overlay renderings, using OnGUI is actually one of the simplest solution. I made this FixedUpdate simulation completely in OnGUI
About immediate mode rendering in general, there are a few things you should keep in mind. There are several internal states that are relevant for rendering. Namely the current viewport, projection matrix and model view matrix. Besides that the active shader pass and all of its parameters. Depending on the method you want to use, certain things may already be setup for you. For example the viewport and projection matrix is usually given by the current camera.
It highly depends on your exact needs what you may or should do. Here are a few related questions:
Your answer
Follow this Question
Related Questions
Gizmos and Drawing a Plane with Rotation 2 Answers
How to draw a filled rectangle through script 1 Answer
Why can't I see my Gizmos Line?? 0 Answers
Drawing Ellipsoid 1 Answer
Draw a circle arround objects 2 Answers