After creating some Sci-Fi attacks like the Rainbow Lazer or the Ro-Cat-Paw Launcher we thought the next special attack should be something more RPG like. So this Blogpost is about how I created a cool chaining lightning strike.
The main idea behind the lightning is to have some line renderers between enemies and generate random line renderer points to get some movement into it. To get amount of points I callculate the distance from the lightning source to its target and split it into segments. After that i know how much points I need. To get the distance between our hero and the enemies I maintain a list of all alive enemies. Just add some randomness and you are almost done.
To make the line renderers look like lightnings I used a texture with a gradient. To make it even more better looking I added one more line renderer simulating a light.
For creating single lightning Bolts I created a separate class:
using UnityEngine;
using System.Collections;
using System.Collections.Generic;
public class ChainLightning : MonoBehaviour{
[Header("Prefabs")]
public GameObject lineRendererPrefab;
public GameObject lightRendererPrefab;
[Header("Config")]
public int chainLength;
public int lightnings;
private float nextRefresh;
private float segmentLength=0.2f;
private List LightningBolts{get; set;}
private List Targets{get; set;}
void Awake(){
LightningBolts=new List();
Targets=new List();
LightningBolt tmpLightningBolt;
for(int i=0;i < chainLength;i++){
tmpLightningBolt=new LightningBolt(segmentLength, i);
tmpLightningBolt.Init(lightnings, lineRendererPrefab, lightRendererPrefab);
LightningBolts.Add(tmpLightningBolt);
}
BuildChain();
}
public void BuildChain(){
//Build a chain, in a real project this might be enemies ;)
for(int i=0;i < chainLength;i++){
Targets.Add(new Vector2(Random.Range (-2f, 2f), Random.Range (-2f, 2f)));
LightningBolts[i].Activate();
}
}
void Update(){
//Refresh the LightningBolts
if(Time.time>nextRefresh){
BuildChain();
for(int i=0;i < Targets.Count;i++){
if(i==0){
LightningBolts[i].DrawLightning(Vector2.zero, Targets[i]);
}else{
LightningBolts[i].DrawLightning(Targets[i-1], Targets[i]);
}
}
nextRefresh=Time.time+0.01f;
}
}
}
To draw the actual lightning segments I created another class:
using UnityEngine;
using System.Collections;
public class LightningBolt {
public LineRenderer[] lineRenderer{get; set;}
public LineRenderer lightRenderer{get; set;}
public float SegmentLength{get; set;}
public int Index{get; private set;}
public bool IsActive{get; private set;}
public LightningBolt(float segmentLength, int index){
SegmentLength=segmentLength;
Index=index;
}
public void Init(int lineRendererCount,
GameObject lineRendererPrefab, GameObject lightRendererPrefab){
//Create the needed LineRenderer instances
lineRenderer=new LineRenderer[lineRendererCount];
for(int i=0;i < lineRendererCount;i++){
lineRenderer[i]=(GameObject.Instantiate(lineRendererPrefab) as GameObject)
.GetComponent();
lineRenderer[i].enabled=false;
}
lightRenderer=(GameObject.Instantiate(lightRendererPrefab) as GameObject)
.GetComponent();
IsActive=false;
}
public void Activate(){
//Active this LightningBolt with all of its LineRenderers
for(int i=0;i < lineRenderer.Length;i++){
lineRenderer[i].enabled=true;
}
lightRenderer.enabled=true;
IsActive=true;
}
public void DrawLightning(Vector2 source, Vector2 target){
//Calculated amount of Segments
float distance=Vector2.Distance(source, target);
int segments=5;
if(distance > SegmentLength){
segments=Mathf.FloorToInt( distance / SegmentLength)+2;
}else{
segments=4;
}
for(int i=0;i < lineRenderer.Length;i++){
// Set the amount of points to the calculated value
lineRenderer[i].SetVertexCount(segments);
lineRenderer[i].SetPosition(0, source);
Vector2 lastPosition=source;
for(int j=1;j < segments-1;j++){
//Go linear from source to target
Vector2 tmp=Vector2.Lerp(source, target, (float)j / (float)segments);
//Add randomness
lastPosition=new Vector2(tmp.x+Random.Range(-0.1f, 0.1f),
tmp.y+Random.Range(-0.1f, 0.1f));
//Set the calculated position
lineRenderer[i].SetPosition(j, lastPosition);
}
lineRenderer[i].SetPosition(segments-1, target);
}
//Set the points for the light
lightRenderer.SetPosition(0, source);
lightRenderer.SetPosition(1, target);
//Set the color of the light
Color lightColor=new Color(0.5647f, 0.58823f, 1f, Random.Range (0.2f, 1f));
lightRenderer.SetColors(lightColor, lightColor);
}
}
The Result
DOWNLOAD UNITY 5 SAMPLE PROJECT
As usual, we want to share a sample project with you – so, it's much easier to understand what we are talking about. Same as last time, be fair and please don't use the graphic assets in your own games.