- Home /
Disabling a lineRender or Ray when there is no target
My goal is to create a grid of posts which charge up and randomly strike neighboring posts with a bolt of electricity. Everything is working as far as finding targets and displaying the lightning, but a strong patterns occurs where the lighting appears between forward and back posts more often than left and right posts. When the charge of two neighboring do not add up to a full charge, there should be no lightning but its seems to default to forward and back. I added an else statement at line 74 to set its target transform to itself so that the lightning would just stay on the single post but that causes the lightning to only appear between forward and back posts which doesn't make sense to me. I think there is some sort of default target appearing due to the order in which the raycasts are executed but I don’t know how to attack that problem.
To set up the scene just put this script on spheres that are in a grid of at least 3x3 with a 10 unit spacing. Make sure to add a line render to the game object with 5 positions. Also, a strange thing happens if any objects in the grid are within 10 units or so of the origin, the objects will not build a charge. This is not a big problem because I have no need to place a grid near the origin but if anyone knows how to fix it I won’t be disappointed.
Thanks!
var readyTarget : Transform;
private var targetZero : Transform;
private var target : Transform[] = new Transform[4];
var radius : float = 10;
private var iWait : float;
private var lineWidth : float;
var layerMask : LayerMask;
private var hit : RaycastHit;
private var touch : RaycastHit;
private var lineRenderer : LineRenderer;
function Start()
{
targetZero = gameObject.transform;
lineRenderer = gameObject.GetComponent(LineRenderer);
lineRenderer.enabled = false;
// This finds nearby targets in a 10 unit radius
var directionRay : Vector3[] = new Vector3[5];
directionRay[0] = Vector3.right*10;
directionRay[1] = Vector3.left*10;
directionRay[2] = Vector3.forward*10;
directionRay[3] = Vector3.back*10;
// This is where taget postions are set based on a raycasthit
for (var n=0; n < 5; n++)
{
if (Physics.Raycast (transform.position, directionRay[n], touch, 200, layerMask));
{
if (!touch.transform)
{
continue;
}
else
{
target[n] = touch.transform;
}
}
}
Charge();
}
var charge : float;
var chargeCombo : float;
var charging : boolean = true;
// This functions monitors and updates the charge
function Charge()
{
charge = Random.Range(0.0, 5.0);
while(chargeCombo < 10.0)
{
yield WaitForSeconds(1);
charge += 1;
for (var j = 0; j < target.Length; j++)
{
if (!target[j])
{
continue;
}
else
{
var otherCharge : float = target[j].gameObject.GetComponent(LightningPolesScript).charge;
chargeCombo = (otherCharge + charge);
if(chargeCombo >= 10)
readyTarget = target[j];
// This "else" should fix the default error I mentioned, but insted it causes the lineRender
// to only be drawn forward or back
//else
//readyTarget = targetZero;
}
}
}
charging = false;
chargeCombo = 0;
}
function FixedUpdate ()
{
if(charging == false)
{
Charge ();
charging = true;
}
if (readyTarget)
{
Zap();
}
}
// This Draws the lightning and raycast that destoys gameobjects
function Zap()
{
lineRenderer.SetPosition(0,transform.position);
for(var i:float=1;i<4;i += 1)
{
lineWidth = Random.Range(0.1f, 0.9f);
lineRenderer.SetWidth(lineWidth, lineWidth);
var pos : Vector3;
pos = Vector3.Lerp(transform.position,readyTarget.position,i/4.0f);
pos.x += Random.Range(-0.4f,0.4f);
pos.z += Random.Range(-0.4f,0.4f);
lineRenderer.enabled = true;
lineRenderer.SetPosition(i,pos);
lineRenderer.SetPosition(target.length,readyTarget.position);
var rayDirection = readyTarget.position - transform.position;
Physics.Raycast (transform.position, rayDirection, hit, 200, layerMask);
if(hit.collider)
hit.collider.SendMessageUpwards("Kill", SendMessageOptions.DontRequireReceiver);
}
}
Answer by sparkzbarca · Jan 01, 2014 at 09:30 AM
because it goes through target list in order and that target list comes from an ordered raycast it isn't random.
So what you need to do is randomize picking from target list instead of for looping through it.
// This finds nearby targets in a 10 unit radius
var directionRay : Vector3[] = new Vector3[5];
directionRay[0] = Vector3.right*10;
directions dont work that way, there is no need to multiply by 10 it does nothing
a direction is just that, it doesnt have a length, it doesnt make sense to speak of the length of right or left or north or west.
thats a line which has a length but in this case if you want to go only 10 max youd do
(Physics.Raycast (transform.position, directionRay[n], touch, 200, layerMask)
and change the 200 to 10 so it stopped after 10 meters.
lastly your not raycasting properly
you need to change direction ray to a local direction.
so
directionRay[0] = Vector3.right*10;
directionRay[1] = Vector3.left*10;
... ..
should be
directionRay[0] = transform.right
directionRay[1] = transform.left;
there are also some things you should do just as good coding practice.
hit.collider.SendMessageUpwards("Kill", SendMessageOptions.DontRequireReceiver);
}
never use sendmessage, always getcomponent the script. ESPECIALLY with dontrequireReceiver tagged its just a horrible thing. The issue is that if you ever were to rename the Kill function for example you'd get no error from this function trying to call it in the compiler and with dont require receiver you wouldnt even get an error at runtime.
calling a function with a string is just terrible because its so unsafe compared to the alternatives and not only that the stupid thing uses recursion so its slow as hell to boot.