added animation package and made small changes

This commit is contained in:
Lorenzo
2022-12-06 17:46:58 +01:00
parent 564ec183d7
commit 3f3323449f
3440 changed files with 12815908 additions and 344 deletions

View File

@@ -0,0 +1,9 @@
fileFormatVersion: 2
guid: 40587c37bffeec44581d661b302b88ce
folderAsset: yes
timeCreated: 1470101287
licenseType: Store
DefaultImporter:
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,9 @@
fileFormatVersion: 2
guid: ad67b6f6ac17a1c44bb26a6ecd06e9ea
folderAsset: yes
timeCreated: 1485465640
licenseType: Store
DefaultImporter:
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,157 @@
// =================================
// Namespaces.
// =================================
using UnityEngine;
// =================================
// Define namespace.
// =================================
namespace MirzaBeig
{
namespace Scripting
{
namespace Effects
{
// =================================
// Classes.
// =================================
public class AttractionParticleAffector : ParticleAffector
{
// =================================
// Nested classes and structures.
// =================================
// ...
// =================================
// Variables.
// =================================
// ...
[Header("Affector Controls")]
public float arrivalRadius = 1.0f;
public float arrivedRadius = 0.5f;
float arrivalRadiusSqr;
float arrivedRadiusSqr;
// =================================
// Functions.
// =================================
// ...
protected override void Awake()
{
base.Awake();
}
// ...
protected override void Start()
{
base.Start();
}
// ...
protected override void Update()
{
base.Update();
}
// ...
protected override void LateUpdate()
{
float uniformTransformScale = transform.lossyScale.x;
arrivalRadiusSqr = (arrivalRadius * arrivalRadius) * uniformTransformScale;
arrivedRadiusSqr = (arrivedRadius * arrivedRadius) * uniformTransformScale;
// ...
base.LateUpdate();
}
// ...
protected override Vector3 GetForce()
{
Vector3 force;
if (parameters.distanceToAffectorCenterSqr < arrivedRadiusSqr)
{
force.x = 0.0f;
force.y = 0.0f;
force.z = 0.0f;
}
else if (parameters.distanceToAffectorCenterSqr < arrivalRadiusSqr)
{
float inverseArrivalScaleNormalized = 1.0f - (parameters.distanceToAffectorCenterSqr / arrivalRadiusSqr);
force = Vector3.Normalize(parameters.scaledDirectionToAffectorCenter) * inverseArrivalScaleNormalized;
}
else
{
force = Vector3.Normalize(parameters.scaledDirectionToAffectorCenter);
}
return force;
}
// ...
protected override void OnDrawGizmosSelected()
{
if (enabled)
{
base.OnDrawGizmosSelected();
// ...
float uniformTransformScale = transform.lossyScale.x;
float arrivalRadius = this.arrivalRadius * uniformTransformScale;
float arrivedRadius = this.arrivedRadius * uniformTransformScale;
Vector3 center = transform.position + offset;
Gizmos.color = Color.yellow;
Gizmos.DrawWireSphere(center, arrivalRadius);
Gizmos.color = Color.red;
Gizmos.DrawWireSphere(center, arrivedRadius);
//Gizmos.color = Color.white;
//Gizmos.DrawLine(currentParticleSystem.transform.position, center);
}
}
// =================================
// End functions.
// =================================
}
// =================================
// End namespace.
// =================================
}
}
}
// =================================
// --END-- //
// =================================

View File

@@ -0,0 +1,12 @@
fileFormatVersion: 2
guid: 3bf6d970cd2b79547a98f2dbf434935f
timeCreated: 1470567812
licenseType: Store
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,12 @@
fileFormatVersion: 2
guid: d566a25d31a988844a80d2747af4986e
timeCreated: 1458196122
licenseType: Store
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,553 @@
// =================================
// Namespaces.
// =================================
using UnityEngine;
using System.Collections.Generic;
// =================================
// Define namespace.
// =================================
namespace MirzaBeig
{
namespace Scripting
{
namespace Effects
{
// =================================
// Classes.
// =================================
public abstract class ParticleAffector : MonoBehaviour
{
// =================================
// Nested classes and structures.
// =================================
// ...
protected struct GetForceParameters
{
public float distanceToAffectorCenterSqr;
public Vector3 scaledDirectionToAffectorCenter;
public Vector3 particlePosition;
}
// =================================
// Variables.
// =================================
// ...
[Header("Common Controls")]
public float radius = Mathf.Infinity;
public float force = 5.0f;
public Vector3 offset = Vector3.zero;
public float scaledRadius
{
get
{
return radius * transform.lossyScale.x;
}
}
float _radius;
float radiusSqr;
float forceDeltaTime;
Vector3 transformPosition;
float[] particleSystemExternalForcesMultipliers;
public AnimationCurve scaleForceByDistance = new AnimationCurve(
new Keyframe(0.0f, 1.0f),
new Keyframe(1.0f, 1.0f)
);
// If (attached to a particle system): forces will be LOCAL.
// Else if (attached to a particle system): forces will be SELECTIVE.
// Else: forces will be GLOBAL.
new ParticleSystem particleSystem;
public List<ParticleSystem> _particleSystems;
int particleSystemsCount;
// All required particle systems that will actually be used.
List<ParticleSystem> particleSystems = new List<ParticleSystem>();
// Particles in each system.
// Second dimension initialized to max particle count
// and not modified unless max particle count for that system changes.
// Prevents allocations each frame.
ParticleSystem.Particle[][] particleSystemParticles;
ParticleSystem.MainModule[] particleSystemMainModules;
Renderer[] particleSystemRenderers;
// ^I could also just put the system and the module in a struct and make a 2D array
// instead of having a seperate array for the modules.
// Current iteration of the particle systems when looping through all of them.
// Useful to derived classes (like for the vortex particle affector).
protected ParticleSystem currentParticleSystem;
// Parameters used by derived force classes.
protected GetForceParameters parameters;
// Update even when entire particle system is invisible?
// Default: FALSE -> if all particles are invisible/offscreen,
// update will not execute.
public bool alwaysUpdate = false;
// =================================
// Functions.
// =================================
// ...
protected virtual void Awake()
{
}
// ...
protected virtual void Start()
{
particleSystem = GetComponent<ParticleSystem>();
}
// Called once per particle system, before entering second loop for its particles.
// Used for setting up based on particle system-specific data.
protected virtual void PerParticleSystemSetup()
{
}
// Direction is NOT normalized.
protected virtual Vector3 GetForce()
{
return Vector3.zero;
}
// ...
protected virtual void Update()
{
}
// Add/remove from public list of particles being managed.
// Remember that adding specific systems will override all
// other contexts (global and pure local).
// Duplicates are not checked (intentionally).
public void AddParticleSystem(ParticleSystem particleSystem)
{
_particleSystems.Add(particleSystem);
}
public void RemoveParticleSystem(ParticleSystem particleSystem)
{
_particleSystems.Remove(particleSystem);
}
// ...
protected virtual void LateUpdate()
{
_radius = scaledRadius;
radiusSqr = _radius * _radius;
forceDeltaTime = force * Time.deltaTime;
transformPosition = transform.position + offset;
// SELECTIVE.
// If manually assigned a set of systems, use those no matter what.
if (_particleSystems.Count != 0)
{
// If editor array size changed, clear and add again.
if (particleSystems.Count != _particleSystems.Count)
{
particleSystems.Clear();
particleSystems.AddRange(_particleSystems);
}
// Else if array size is the same, then re-assign from
// the editor array. I do this in case the elements are different
// even though the size is the same.
else
{
for (int i = 0; i < _particleSystems.Count; i++)
{
particleSystems[i] = _particleSystems[i];
}
}
}
// LOCAL.
// Else if attached to particle system, use only that.
// Obviously, this will only happen if there are no systems specified in the array.
else if (particleSystem)
{
// If just one element, assign as local PS component.
if (particleSystems.Count == 1)
{
particleSystems[0] = particleSystem;
}
// Else, clear entire array and add only the one.
else
{
particleSystems.Clear();
particleSystems.Add(particleSystem);
}
}
// GLOBAL.
// Else, take all the ones from the entire scene.
// This is the most expensive since it searches the entire scene
// and also requires an allocation for every frame due to not knowing
// if the particle systems are all the same from the last frame unless
// I had a list to compare to from last frame. In that case, I'm not sure
// if the performance would be better or worse. Do a test later?
else
{
particleSystems.Clear();
particleSystems.AddRange(FindObjectsOfType<ParticleSystem>());
}
parameters = new GetForceParameters();
particleSystemsCount = particleSystems.Count;
// If first frame (array is null) or length is less than the number of systems, initialize size of array.
// I never shrink the array. Not sure if that's potentially super bad? I could always throw in a public
// bool as an option to allow shrinking since there's a performance benefit for each, but depends on the
// implementation case.
if (particleSystemParticles == null || particleSystemParticles.Length < particleSystemsCount)
{
particleSystemParticles = new ParticleSystem.Particle[particleSystemsCount][];
particleSystemMainModules = new ParticleSystem.MainModule[particleSystemsCount];
particleSystemRenderers = new Renderer[particleSystemsCount];
particleSystemExternalForcesMultipliers = new float[particleSystemsCount];
for (int i = 0; i < particleSystemsCount; i++)
{
particleSystemMainModules[i] = particleSystems[i].main;
particleSystemRenderers[i] = particleSystems[i].GetComponent<Renderer>();
particleSystemExternalForcesMultipliers[i] = particleSystems[i].externalForces.multiplier;
}
}
for (int i = 0; i < particleSystemsCount; i++)
{
if (!particleSystemRenderers[i].isVisible && !alwaysUpdate)
{
continue;
}
int maxParticles = particleSystemMainModules[i].maxParticles;
if (particleSystemParticles[i] == null || particleSystemParticles[i].Length < maxParticles)
{
particleSystemParticles[i] = new ParticleSystem.Particle[maxParticles];
}
currentParticleSystem = particleSystems[i];
PerParticleSystemSetup();
int particleCount = currentParticleSystem.GetParticles(particleSystemParticles[i]);
ParticleSystemSimulationSpace simulationSpace = particleSystemMainModules[i].simulationSpace;
ParticleSystemScalingMode scalingMode = particleSystemMainModules[i].scalingMode;
// I could also store the transforms in an array similar to what I do with modules.
// Or, put all of those together into a struct and make an array out of that since
// they'll always be assigned/updated at the same time.
Transform currentParticleSystemTransform = currentParticleSystem.transform;
Transform customSimulationSpaceTransform = particleSystemMainModules[i].customSimulationSpace;
// If in world space, there's no need to do any of the extra calculations... simplify the loop!
if (simulationSpace == ParticleSystemSimulationSpace.World)
{
for (int j = 0; j < particleCount; j++)
{
parameters.particlePosition = particleSystemParticles[i][j].position;
parameters.scaledDirectionToAffectorCenter.x = transformPosition.x - parameters.particlePosition.x;
parameters.scaledDirectionToAffectorCenter.y = transformPosition.y - parameters.particlePosition.y;
parameters.scaledDirectionToAffectorCenter.z = transformPosition.z - parameters.particlePosition.z;
parameters.distanceToAffectorCenterSqr = parameters.scaledDirectionToAffectorCenter.sqrMagnitude;
if (parameters.distanceToAffectorCenterSqr < radiusSqr)
{
float distanceToCenterNormalized = parameters.distanceToAffectorCenterSqr / radiusSqr;
float distanceScale = scaleForceByDistance.Evaluate(distanceToCenterNormalized);
Vector3 force = GetForce();
float forceScale = (forceDeltaTime * distanceScale) * particleSystemExternalForcesMultipliers[i];
force.x *= forceScale;
force.y *= forceScale;
force.z *= forceScale;
Vector3 particleVelocity = particleSystemParticles[i][j].velocity;
particleVelocity.x += force.x;
particleVelocity.y += force.y;
particleVelocity.z += force.z;
particleSystemParticles[i][j].velocity = particleVelocity;
}
}
}
else
{
Vector3 particleSystemPosition = Vector3.zero;
Quaternion particleSystemRotation = Quaternion.identity;
Vector3 particleSystemLocalScale = Vector3.one;
Transform simulationSpaceTransform = currentParticleSystemTransform;
switch (simulationSpace)
{
case ParticleSystemSimulationSpace.Local:
{
particleSystemPosition = simulationSpaceTransform.position;
particleSystemRotation = simulationSpaceTransform.rotation;
particleSystemLocalScale = simulationSpaceTransform.localScale;
break;
}
case ParticleSystemSimulationSpace.Custom:
{
simulationSpaceTransform = customSimulationSpaceTransform;
particleSystemPosition = simulationSpaceTransform.position;
particleSystemRotation = simulationSpaceTransform.rotation;
particleSystemLocalScale = simulationSpaceTransform.localScale;
break;
}
default:
{
throw new System.NotSupportedException(
string.Format("Unsupported scaling mode '{0}'.", simulationSpace));
}
}
for (int j = 0; j < particleCount; j++)
{
parameters.particlePosition = particleSystemParticles[i][j].position;
switch (simulationSpace)
{
case ParticleSystemSimulationSpace.Local:
case ParticleSystemSimulationSpace.Custom:
{
switch (scalingMode)
{
case ParticleSystemScalingMode.Hierarchy:
{
parameters.particlePosition = simulationSpaceTransform.TransformPoint(particleSystemParticles[i][j].position);
break;
}
case ParticleSystemScalingMode.Local:
{
// Order is important.
parameters.particlePosition = Vector3.Scale(parameters.particlePosition, particleSystemLocalScale);
parameters.particlePosition = particleSystemRotation * parameters.particlePosition;
parameters.particlePosition = parameters.particlePosition + particleSystemPosition;
break;
}
case ParticleSystemScalingMode.Shape:
{
parameters.particlePosition = particleSystemRotation * parameters.particlePosition;
parameters.particlePosition = parameters.particlePosition + particleSystemPosition;
break;
}
default:
{
throw new System.NotSupportedException(
string.Format("Unsupported scaling mode '{0}'.", scalingMode));
}
}
break;
}
}
parameters.scaledDirectionToAffectorCenter.x = transformPosition.x - parameters.particlePosition.x;
parameters.scaledDirectionToAffectorCenter.y = transformPosition.y - parameters.particlePosition.y;
parameters.scaledDirectionToAffectorCenter.z = transformPosition.z - parameters.particlePosition.z;
parameters.distanceToAffectorCenterSqr = parameters.scaledDirectionToAffectorCenter.sqrMagnitude;
//particleSystemParticles[i][j].velocity += forceDeltaTime * Vector3.Normalize(parameters.scaledDirectionToAffectorCenter);
if (parameters.distanceToAffectorCenterSqr < radiusSqr)
{
// 0.0f -> 0.99...f;
float distanceToCenterNormalized = parameters.distanceToAffectorCenterSqr / radiusSqr;
// Evaluating a curve within a loop which is very likely to exceed a few thousand
// iterations produces a noticeable FPS drop (around minus 2 - 5). Might be a worthwhile
// optimization to check outside all loops if the curve is constant (all keyframes same value),
// and then run a different block of code if true that uses that value as a stored float without
// having to call Evaluate(t).
float distanceScale = scaleForceByDistance.Evaluate(distanceToCenterNormalized);
// Expanded vector operations for optimization. I think this is already done by
// the compiler, but it's nice to have for the editor anyway.
Vector3 force = GetForce();
float forceScale = (forceDeltaTime * distanceScale) * particleSystemExternalForcesMultipliers[i];
force.x *= forceScale;
force.y *= forceScale;
force.z *= forceScale;
switch (simulationSpace)
{
case ParticleSystemSimulationSpace.Local:
case ParticleSystemSimulationSpace.Custom:
{
switch (scalingMode)
{
case ParticleSystemScalingMode.Hierarchy:
{
force = simulationSpaceTransform.InverseTransformVector(force);
break;
}
case ParticleSystemScalingMode.Local:
{
// Order is important.
// Notice how rotation and scale orders are reversed.
force = Quaternion.Inverse(particleSystemRotation) * force;
force = Vector3.Scale(force, new Vector3(
1.0f / particleSystemLocalScale.x,
1.0f / particleSystemLocalScale.y,
1.0f / particleSystemLocalScale.z));
break;
}
case ParticleSystemScalingMode.Shape:
{
force = Quaternion.Inverse(particleSystemRotation) * force;
break;
}
// This would technically never execute since it's checked earlier (above).
default:
{
throw new System.NotSupportedException(
string.Format("Unsupported scaling mode '{0}'.", scalingMode));
}
}
break;
}
}
Vector3 particleVelocity = particleSystemParticles[i][j].velocity;
particleVelocity.x += force.x;
particleVelocity.y += force.y;
particleVelocity.z += force.z;
particleSystemParticles[i][j].velocity = particleVelocity;
}
}
}
currentParticleSystem.SetParticles(particleSystemParticles[i], particleCount);
}
}
// ...
void OnApplicationQuit()
{
}
// ...
protected virtual void OnDrawGizmosSelected()
{
Gizmos.color = Color.green;
Gizmos.DrawWireSphere(transform.position + offset, scaledRadius);
}
// =================================
// End functions.
// =================================
}
// =================================
// End namespace.
// =================================
}
}
}
// =================================
// --END-- //
// =================================

View File

@@ -0,0 +1,12 @@
fileFormatVersion: 2
guid: 9fbb01249b8f1d8419cf21b6846cb507
timeCreated: 1470567813
licenseType: Store
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,263 @@
// =================================
// Namespaces.
// =================================
using UnityEngine;
// =================================
// Define namespace.
// =================================
namespace MirzaBeig
{
namespace Scripting
{
namespace Effects
{
// =================================
// Classes.
// =================================
public class TurbulenceParticleAffector : ParticleAffector
{
// =================================
// Nested classes and structures.
// =================================
// ...
public enum NoiseType
{
PseudoPerlin,
Perlin,
Simplex,
OctavePerlin,
OctaveSimplex
}
// =================================
// Variables.
// =================================
// ...
[Header("Affector Controls")]
public float speed = 1.0f;
[Range(0.0f, 8.0f)]
public float frequency = 1.0f;
public NoiseType noiseType = NoiseType.Perlin;
// ...
[Header("Octave Variant-Only Controls")]
[Range(1, 8)]
public int octaves = 1;
[Range(0.0f, 4.0f)]
public float lacunarity = 2.0f;
[Range(0.0f, 1.0f)]
public float persistence = 0.5f;
float time;
// Noise start offsets.
float randomX;
float randomY;
float randomZ;
// Final offset.
float offsetX;
float offsetY;
float offsetZ;
// =================================
// Functions.
// =================================
// ...
protected override void Awake()
{
base.Awake();
}
// ...
protected override void Start()
{
base.Start();
// ...
randomX = Random.Range(-32.0f, 32.0f);
randomY = Random.Range(-32.0f, 32.0f);
randomZ = Random.Range(-32.0f, 32.0f);
}
// ...
protected override void Update()
{
time = Time.time;
// ...
base.Update();
}
// ...
protected override void LateUpdate()
{
offsetX = (time * speed) + randomX;
offsetY = (time * speed) + randomY;
offsetZ = (time * speed) + randomZ;
// ...
base.LateUpdate();
}
// ...
protected override Vector3 GetForce()
{
// I could also pre-multiply the frequency, but
// all the octave variants also use frequency
// within themselves, so it would cause redundant
// multiplication.
float xX = parameters.particlePosition.x + offsetX;
float yX = parameters.particlePosition.y + offsetX;
float zX = parameters.particlePosition.z + offsetX;
float xY = parameters.particlePosition.x + offsetY;
float yY = parameters.particlePosition.y + offsetY;
float zY = parameters.particlePosition.z + offsetY;
float xZ = parameters.particlePosition.x + offsetZ;
float yZ = parameters.particlePosition.y + offsetZ;
float zZ = parameters.particlePosition.z + offsetZ;
Vector3 force;
switch (noiseType)
{
case NoiseType.PseudoPerlin:
{
// This isn't really right, but... it gives believable-enough results.
// It's also much faster than real perlin noise.
// It works well where you don't have to animate a large field where
// the repeating pattern would otherwise be easily seen.
// Examples of good uses: smoke trail particle turbulence.
// Example of bad uses: particle box simulating waves or something...
float noiseX = Mathf.PerlinNoise(xX * frequency, yY * frequency);
float noiseY = Mathf.PerlinNoise(xX * frequency, zY * frequency);
float noiseZ = Mathf.PerlinNoise(xX * frequency, xY * frequency);
noiseX = Mathf.Lerp(-1.0f, 1.0f, noiseX);
noiseY = Mathf.Lerp(-1.0f, 1.0f, noiseY);
noiseZ = Mathf.Lerp(-1.0f, 1.0f, noiseZ);
Vector3 forceX = (Vector3.right * noiseX);
Vector3 forceY = (Vector3.up * noiseY);
Vector3 forceZ = (Vector3.forward * noiseZ);
force = forceX + forceY + forceZ;
break;
}
// ...
default:
case NoiseType.Perlin:
{
force.x = Noise.perlin(xX * frequency, yX * frequency, zX * frequency);
force.y = Noise.perlin(xY * frequency, yY * frequency, zY * frequency);
force.z = Noise.perlin(xZ * frequency, yZ * frequency, zZ * frequency);
return force;
}
// ...
case NoiseType.Simplex:
{
force.x = Noise.simplex(xX * frequency, yX * frequency, zX * frequency);
force.y = Noise.simplex(xY * frequency, yY * frequency, zY * frequency);
force.z = Noise.simplex(xZ * frequency, yZ * frequency, zZ * frequency);
break;
}
// ...
case NoiseType.OctavePerlin:
{
force.x = Noise.octavePerlin(xX, yX, zX, frequency, octaves, lacunarity, persistence);
force.y = Noise.octavePerlin(xY, yY, zY, frequency, octaves, lacunarity, persistence);
force.z = Noise.octavePerlin(xZ, yZ, zZ, frequency, octaves, lacunarity, persistence);
break;
}
case NoiseType.OctaveSimplex:
{
force.x = Noise.octaveSimplex(xX, yX, zX, frequency, octaves, lacunarity, persistence);
force.y = Noise.octaveSimplex(xY, yY, zY, frequency, octaves, lacunarity, persistence);
force.z = Noise.octaveSimplex(xZ, yZ, zZ, frequency, octaves, lacunarity, persistence);
break;
}
}
return force;
}
// ...
protected override void OnDrawGizmosSelected()
{
if (enabled)
{
base.OnDrawGizmosSelected();
}
}
// =================================
// End functions.
// =================================
}
// =================================
// End namespace.
// =================================
}
}
}
// =================================
// --END-- //
// =================================

View File

@@ -0,0 +1,12 @@
fileFormatVersion: 2
guid: 80ca8d20214f40846b9e49b318255592
timeCreated: 1470567813
licenseType: Store
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,164 @@
// =================================
// Namespaces.
// =================================
using UnityEngine;
// =================================
// Define namespace.
// =================================
namespace MirzaBeig
{
namespace Scripting
{
namespace Effects
{
// =================================
// Classes.
// =================================
public class VortexParticleAffector : ParticleAffector
{
// =================================
// Nested classes and structures.
// =================================
// ...
// =================================
// Variables.
// =================================
// ...
Vector3 axisOfRotation;
[Header("Affector Controls")]
// Useful if particle affector and particle system
// are on the same game object, and you need a seperate
// rotation for the system, and the affector, but don't
// want to make the two different game objects.
public Vector3 axisOfRotationOffset = Vector3.zero;
// =================================
// Functions.
// =================================
// ...
protected override void Awake()
{
base.Awake();
}
// ...
protected override void Start()
{
base.Start();
}
// ...
protected override void Update()
{
base.Update();
}
// ...
protected override void LateUpdate()
{
base.LateUpdate();
}
// ...
void UpdateAxisOfRotation()
{
axisOfRotation = Quaternion.Euler(axisOfRotationOffset) * transform.up;
}
// ...
protected override void PerParticleSystemSetup()
{
UpdateAxisOfRotation();
}
// ...
protected override Vector3 GetForce()
{
// With no rotation, looking at the PS with the vortex down the Z axis, you may
// think it's spinning the wrong way because it's counter-clockwise. But it's actually correct...
// Because if you were to look up aligned with the up-axis of the vortex, you'd see it spinning
// clockwise. And if that up was inverted (you looked down at the vortex from above), then it would
// be spinning counter-clockwise since now the vector of rotation is point at you, not away from you.
// I can't believe I almost mixed that up by adding a negative (-) in front of the return.
return Vector3.Normalize(Vector3.Cross(axisOfRotation, parameters.scaledDirectionToAffectorCenter));
}
// ...
protected override void OnDrawGizmosSelected()
{
if (enabled)
{
base.OnDrawGizmosSelected();
// ...
Gizmos.color = Color.red;
// When not playing, I don't have a reference to the specific particle system,
// so just use the default method of showing the axis of rotation (which may be wrong).
// There's no easy way around this since I may have several particle systems being updated
// with a single vortex. It's just a visual guide anyways, so no big deal, I suppose.
Vector3 axisOfRotation;
if (Application.isPlaying && enabled)
{
UpdateAxisOfRotation();
axisOfRotation = this.axisOfRotation;
}
else
{
axisOfRotation = Quaternion.Euler(axisOfRotationOffset) * transform.up;
}
Gizmos.DrawLine(transform.position + offset, (transform.position + offset) + (axisOfRotation * scaledRadius));
}
}
// =================================
// End functions.
// =================================
}
// =================================
// End namespace.
// =================================
}
}
}
// =================================
// --END-- //
// =================================

View File

@@ -0,0 +1,12 @@
fileFormatVersion: 2
guid: 39e8c956cffbc4b4ba68531bef53e1d4
timeCreated: 1470567812
licenseType: Store
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,9 @@
fileFormatVersion: 2
guid: 35f64f26eb6e5f04bb370e3f131891db
folderAsset: yes
timeCreated: 1488921461
licenseType: Store
DefaultImporter:
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,400 @@
// =================================
// Namespaces.
// =================================
using UnityEngine;
using System.Collections.Generic;
// =================================
// Define namespace.
// =================================
namespace MirzaBeig
{
namespace Scripting
{
namespace Effects
{
// =================================
// Classes.
// =================================
[RequireComponent(typeof(ParticleSystem))]
public class ParticleFlocking : MonoBehaviour
{
// =================================
// Nested classes and structures.
// =================================
// ...
public struct Voxel
{
public Bounds bounds;
public int[] particles;
public int particleCount;
}
// =================================
// Variables.
// =================================
// ...
[Header("N^2 Mode Settings")]
public float maxDistance = 0.5f;
[Header("Forces")]
public float cohesion = 0.5f;
public float separation = 0.25f;
[Header("Voxel Mode Settings")]
public bool useVoxels = true;
public bool voxelLocalCenterFromBounds = true;
public float voxelVolume = 8.0f;
public int voxelsPerAxis = 5;
int previousVoxelsPerAxisValue;
Voxel[] voxels;
new ParticleSystem particleSystem;
ParticleSystem.Particle[] particles;
Vector3[] particlePositions;
ParticleSystem.MainModule particleSystemMainModule;
[Header("General Performance Settings")]
[Range(0.0f, 1.0f)]
public float delay = 0.0f;
float timer;
public bool alwaysUpdate = false;
bool visible;
// =================================
// Functions.
// =================================
// ...
void Start()
{
particleSystem = GetComponent<ParticleSystem>();
particleSystemMainModule = particleSystem.main;
}
// ...
void OnBecameVisible()
{
visible = true;
}
void OnBecameInvisible()
{
visible = false;
}
// ...
void buildVoxelGrid()
{
int voxelCount =
voxelsPerAxis * voxelsPerAxis * voxelsPerAxis;
voxels = new Voxel[voxelCount];
float voxelSize = voxelVolume / voxelsPerAxis;
float voxelSizeHalf = voxelSize / 2.0f;
float voxelVolumeHalf = voxelVolume / 2.0f;
Vector3 positionBase = transform.position;
int i = 0;
for (int x = 0; x < voxelsPerAxis; x++)
{
float posX = (-voxelVolumeHalf + voxelSizeHalf) + (x * voxelSize);
for (int y = 0; y < voxelsPerAxis; y++)
{
float posY = (-voxelVolumeHalf + voxelSizeHalf) + (y * voxelSize);
for (int z = 0; z < voxelsPerAxis; z++)
{
float posZ = (-voxelVolumeHalf + voxelSizeHalf) + (z * voxelSize);
voxels[i].particleCount = 0;
voxels[i].bounds = new Bounds(positionBase + new Vector3(posX, posY, posZ), Vector3.one * voxelSize);
i++;
}
}
}
}
// ...
void LateUpdate()
{
if (alwaysUpdate || visible)
{
if (useVoxels)
{
int voxelCount =
voxelsPerAxis * voxelsPerAxis * voxelsPerAxis;
if (voxels == null || voxels.Length < voxelCount)
{
buildVoxelGrid();
}
}
int maxParticles = particleSystemMainModule.maxParticles;
if (particles == null || particles.Length < maxParticles)
{
particles = new ParticleSystem.Particle[maxParticles];
particlePositions = new Vector3[maxParticles];
if (useVoxels)
{
for (int i = 0; i < voxels.Length; i++)
{
voxels[i].particles = new int[maxParticles];
}
}
}
timer += Time.deltaTime;
if (timer >= delay)
{
float deltaTime = timer;
timer = 0.0f;
particleSystem.GetParticles(particles);
int particleCount = particleSystem.particleCount;
float cohesionDeltaTime = cohesion * deltaTime;
float separationDeltaTime = separation * deltaTime;
for (int i = 0; i < particleCount; i++)
{
particlePositions[i] = particles[i].position;
}
if (useVoxels)
{
int voxelCount = voxels.Length;
float voxelSize = voxelVolume / voxelsPerAxis;
for (int i = 0; i < particleCount; i++)
{
for (int j = 0; j < voxelCount; j++)
{
if (voxels[j].bounds.Contains(particlePositions[i]))
{
voxels[j].particles[voxels[j].particleCount] = i;
voxels[j].particleCount++;
break;
}
}
}
for (int i = 0; i < voxelCount; i++)
{
if (voxels[i].particleCount > 1)
{
for (int j = 0; j < voxels[i].particleCount; j++)
{
Vector3 directionToLocalCenter;
Vector3 localCenter = particlePositions[voxels[i].particles[j]];
if (voxelLocalCenterFromBounds)
{
directionToLocalCenter = voxels[i].bounds.center - particlePositions[voxels[i].particles[j]];
}
else
{
for (int k = 0; k < voxels[i].particleCount; k++)
{
if (k == j)
{
continue;
}
localCenter += particlePositions[voxels[i].particles[k]];
}
localCenter /= voxels[i].particleCount;
directionToLocalCenter = localCenter - particlePositions[voxels[i].particles[j]];
}
float distanceToLocalCenterSqr = directionToLocalCenter.sqrMagnitude;
directionToLocalCenter.Normalize();
Vector3 force = Vector3.zero;
force += directionToLocalCenter * cohesionDeltaTime;
force -= directionToLocalCenter * ((1.0f - (distanceToLocalCenterSqr / voxelSize)) * separationDeltaTime);
Vector3 particleVelocity = particles[voxels[i].particles[j]].velocity;
particleVelocity.x += force.x;
particleVelocity.y += force.y;
particleVelocity.z += force.z;
particles[voxels[i].particles[j]].velocity = particleVelocity;
}
voxels[i].particleCount = 0;
}
}
}
else
{
float maxDistanceSqr = maxDistance * maxDistance;
Vector3 p1p2_difference;
for (int i = 0; i < particleCount; i++)
{
int localCount = 1;
Vector3 localCenter = particlePositions[i];
for (int j = 0; j < particleCount; j++)
{
if (j == i)
{
continue;
}
p1p2_difference.x = particlePositions[i].x - particlePositions[j].x;
p1p2_difference.y = particlePositions[i].y - particlePositions[j].y;
p1p2_difference.z = particlePositions[i].z - particlePositions[j].z;
float distanceSqr = Vector3.SqrMagnitude(p1p2_difference);
// TODO: Expand vector arithmetic for performance.
if (distanceSqr <= maxDistanceSqr)
{
localCount++;
localCenter += particlePositions[j];
}
}
if (localCount != 1)
{
localCenter /= localCount;
Vector3 directionToLocalCenter = localCenter - particlePositions[i];
float distanceToLocalCenterSqr = directionToLocalCenter.sqrMagnitude;
directionToLocalCenter.Normalize();
Vector3 force = Vector3.zero;
force += directionToLocalCenter * cohesionDeltaTime;
force -= directionToLocalCenter * ((1.0f - (distanceToLocalCenterSqr / maxDistanceSqr)) * separationDeltaTime);
Vector3 particleVelocity = particles[i].velocity;
particleVelocity.x += force.x;
particleVelocity.y += force.y;
particleVelocity.z += force.z;
particles[i].velocity = particleVelocity;
}
//Vector3 velocity = particles[i].velocity;
//if (velocity != Vector3.zero)
//{
// particles[i].rotation3D = Quaternion.LookRotation(velocity, Vector3.up).eulerAngles;
//}
}
}
particleSystem.SetParticles(particles, particleCount);
}
}
}
// ...
void OnDrawGizmosSelected()
{
//buildVoxelGrid();
//for (int i = 0; i < voxels.Length; i++)
//{
// Gizmos.DrawWireCube(voxels[i].bounds.center, voxels[i].bounds.size);
//}
float size = voxelVolume / voxelsPerAxis;
float sizeHalf = size / 2.0f;
float totalSizeHalf = voxelVolume / 2.0f;
Vector3 positionBase = transform.position;
Gizmos.color = Color.red;
Gizmos.DrawWireCube(positionBase, Vector3.one * voxelVolume);
Gizmos.color = Color.white;
for (int x = 0; x < voxelsPerAxis; x++)
{
float posX = (-totalSizeHalf + sizeHalf) + (x * size);
for (int y = 0; y < voxelsPerAxis; y++)
{
float posY = (-totalSizeHalf + sizeHalf) + (y * size);
for (int z = 0; z < voxelsPerAxis; z++)
{
float posZ = (-totalSizeHalf + sizeHalf) + (z * size);
Gizmos.DrawWireCube(positionBase + new Vector3(posX, posY, posZ), Vector3.one * size);
}
}
}
}
// =================================
// End functions.
// =================================
}
// =================================
// End namespace.
// =================================
}
}
}
// =================================
// --END-- //
// =================================

View File

@@ -0,0 +1,12 @@
fileFormatVersion: 2
guid: dc4f2f91673ed344bbefeab4a66ff936
timeCreated: 1470567812
licenseType: Store
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,9 @@
fileFormatVersion: 2
guid: ced1f8ff08c38be499ef34841ec4fa6d
folderAsset: yes
timeCreated: 1470101287
licenseType: Store
DefaultImporter:
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,9 @@
fileFormatVersion: 2
guid: a74ae461ef09d524ca0587ac54bac419
folderAsset: yes
timeCreated: 1508401765
licenseType: Store
DefaultImporter:
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,320 @@
%YAML 1.1
%TAG !u! tag:unity3d.com,2011:
--- !u!114 &11400000
MonoBehaviour:
m_ObjectHideFlags: 0
m_PrefabParentObject: {fileID: 0}
m_PrefabInternal: {fileID: 0}
m_GameObject: {fileID: 0}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: 8a3bdb2cd68f901469e7cc149151eb49, type: 3}
m_Name: Particle Force Field Post-Processing Profile
m_EditorClassIdentifier:
debugViews:
m_Enabled: 1
m_Settings:
mode: 0
depth:
scale: 1
motionVectors:
sourceOpacity: 1
motionImageOpacity: 0
motionImageAmplitude: 16
motionVectorsOpacity: 1
motionVectorsResolution: 24
motionVectorsAmplitude: 64
fog:
m_Enabled: 0
m_Settings:
excludeSkybox: 1
antialiasing:
m_Enabled: 0
m_Settings:
method: 0
fxaaSettings:
preset: 2
taaSettings:
jitterSpread: 0.75
sharpen: 0.3
stationaryBlending: 0.95
motionBlending: 0.85
ambientOcclusion:
m_Enabled: 0
m_Settings:
intensity: 1
radius: 0.3
sampleCount: 10
downsampling: 1
forceForwardCompatibility: 0
ambientOnly: 0
highPrecision: 0
screenSpaceReflection:
m_Enabled: 0
m_Settings:
reflection:
blendType: 0
reflectionQuality: 2
maxDistance: 100
iterationCount: 256
stepSize: 3
widthModifier: 0.5
reflectionBlur: 1
reflectBackfaces: 0
intensity:
reflectionMultiplier: 1
fadeDistance: 100
fresnelFade: 1
fresnelFadePower: 1
screenEdgeMask:
intensity: 0.03
depthOfField:
m_Enabled: 0
m_Settings:
focusDistance: 5
aperture: 5.6
focalLength: 50
useCameraFov: 0
kernelSize: 1
motionBlur:
m_Enabled: 0
m_Settings:
shutterAngle: 270
sampleCount: 10
frameBlending: 0
eyeAdaptation:
m_Enabled: 0
m_Settings:
lowPercent: 45
highPercent: 95
minLuminance: -5
maxLuminance: 1
keyValue: 0.25
dynamicKeyValue: 1
adaptationType: 0
speedUp: 2
speedDown: 1
logMin: -8
logMax: 4
bloom:
m_Enabled: 1
m_Settings:
bloom:
intensity: 5
threshold: 0.5
softKnee: 0
radius: 5.5
antiFlicker: 0
lensDirt:
texture: {fileID: 0}
intensity: 3
colorGrading:
m_Enabled: 1
m_Settings:
tonemapping:
tonemapper: 1
neutralBlackIn: 0.02
neutralWhiteIn: 10
neutralBlackOut: 0
neutralWhiteOut: 10
neutralWhiteLevel: 5.3
neutralWhiteClip: 10
basic:
postExposure: 2
temperature: 0
tint: 0
hueShift: 0
saturation: 1
contrast: 1
channelMixer:
red: {x: 1, y: 0, z: 0}
green: {x: 0, y: 1, z: 0}
blue: {x: 0, y: 0, z: 1}
currentEditingChannel: 0
colorWheels:
mode: 1
log:
slope: {r: 1, g: 1, b: 1, a: 0}
power: {r: 1, g: 1, b: 1, a: 0}
offset: {r: 1, g: 1, b: 1, a: 0}
linear:
lift: {r: 0, g: 0, b: 0, a: 0}
gamma: {r: 0, g: 0, b: 0, a: 0}
gain: {r: 0, g: 0, b: 0, a: 0}
curves:
master:
curve:
serializedVersion: 2
m_Curve:
- serializedVersion: 2
time: 0
value: 0
inSlope: 1
outSlope: 1
tangentMode: 0
- serializedVersion: 2
time: 1
value: 1
inSlope: 1
outSlope: 1
tangentMode: 0
m_PreInfinity: 2
m_PostInfinity: 2
m_RotationOrder: 0
m_Loop: 0
m_ZeroValue: 0
m_Range: 1
red:
curve:
serializedVersion: 2
m_Curve:
- serializedVersion: 2
time: 0
value: 0
inSlope: 1
outSlope: 1
tangentMode: 0
- serializedVersion: 2
time: 1
value: 1
inSlope: 1
outSlope: 1
tangentMode: 0
m_PreInfinity: 2
m_PostInfinity: 2
m_RotationOrder: 4
m_Loop: 0
m_ZeroValue: 0
m_Range: 1
green:
curve:
serializedVersion: 2
m_Curve:
- serializedVersion: 2
time: 0
value: 0
inSlope: 1
outSlope: 1
tangentMode: 0
- serializedVersion: 2
time: 1
value: 1
inSlope: 1
outSlope: 1
tangentMode: 0
m_PreInfinity: 2
m_PostInfinity: 2
m_RotationOrder: 4
m_Loop: 0
m_ZeroValue: 0
m_Range: 1
blue:
curve:
serializedVersion: 2
m_Curve:
- serializedVersion: 2
time: 0
value: 0
inSlope: 1
outSlope: 1
tangentMode: 0
- serializedVersion: 2
time: 1
value: 1
inSlope: 1
outSlope: 1
tangentMode: 0
m_PreInfinity: 2
m_PostInfinity: 2
m_RotationOrder: 4
m_Loop: 0
m_ZeroValue: 0
m_Range: 1
hueVShue:
curve:
serializedVersion: 2
m_Curve: []
m_PreInfinity: 2
m_PostInfinity: 2
m_RotationOrder: 4
m_Loop: 1
m_ZeroValue: 0.5
m_Range: 1
hueVSsat:
curve:
serializedVersion: 2
m_Curve: []
m_PreInfinity: 2
m_PostInfinity: 2
m_RotationOrder: 4
m_Loop: 1
m_ZeroValue: 0.5
m_Range: 1
satVSsat:
curve:
serializedVersion: 2
m_Curve: []
m_PreInfinity: 2
m_PostInfinity: 2
m_RotationOrder: 4
m_Loop: 0
m_ZeroValue: 0.5
m_Range: 1
lumVSsat:
curve:
serializedVersion: 2
m_Curve: []
m_PreInfinity: 2
m_PostInfinity: 2
m_RotationOrder: 4
m_Loop: 0
m_ZeroValue: 0.5
m_Range: 1
e_CurrentEditingCurve: 0
e_CurveY: 1
e_CurveR: 0
e_CurveG: 0
e_CurveB: 0
userLut:
m_Enabled: 0
m_Settings:
lut: {fileID: 0}
contribution: 1
chromaticAberration:
m_Enabled: 1
m_Settings:
spectralTexture: {fileID: 0}
intensity: 0.5
grain:
m_Enabled: 0
m_Settings:
colored: 1
intensity: 1
size: 0.5
luminanceContribution: 0.8
vignette:
m_Enabled: 1
m_Settings:
mode: 0
color: {r: 0, g: 0, b: 0, a: 1}
center: {x: 0.5, y: 0.5}
intensity: 0.45
smoothness: 0.2
roundness: 1
mask: {fileID: 0}
opacity: 1
rounded: 0
dithering:
m_Enabled: 0
monitors:
currentMonitorID: 0
refreshOnPlay: 0
histogramMode: 3
waveformExposure: 0.12
waveformY: 0
waveformR: 1
waveformG: 1
waveformB: 1
paradeExposure: 0.12
vectorscopeExposure: 0.12
vectorscopeShowBackground: 1

View File

@@ -0,0 +1,9 @@
fileFormatVersion: 2
guid: dc09589739c6fec4bbf14e80ff95ce08
timeCreated: 1508401783
licenseType: Store
NativeFormatImporter:
mainObjectFileID: 11400000
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,9 @@
fileFormatVersion: 2
guid: d8b68c38e6770da4fbcd49976f2773fe
folderAsset: yes
timeCreated: 1508395563
licenseType: Store
DefaultImporter:
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: cb32a6a0595ad4b42b5d833207fe16df
timeCreated: 1508396100
licenseType: Store
DefaultImporter:
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: f489c4d963cccfd4a8fc22284a646a3e
timeCreated: 1508470395
licenseType: Store
DefaultImporter:
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,9 @@
fileFormatVersion: 2
guid: f729b65a61a5a3445a30c10aa956f9e2
folderAsset: yes
timeCreated: 1508398165
licenseType: Store
DefaultImporter:
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,302 @@
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
using UnityEngine.SceneManagement;
using MirzaBeig.Scripting.Effects;
public class ParticleForceFieldsDemo : MonoBehaviour
{
[Header("Overview")]
public Text FPSText;
public Text particleCountText;
public Toggle postProcessingToggle;
public MonoBehaviour postProcessing;
[Header("Particle System Settings")]
new public ParticleSystem particleSystem;
ParticleSystem.MainModule particleSystemMainModule;
ParticleSystem.EmissionModule particleSystemEmissionModule;
public Text maxParticlesText;
public Text particlesPerSecondText;
public Slider maxParticlesSlider;
public Slider particlesPerSecondSlider;
[Header("Attraction Particle Force Field Settings")]
public AttractionParticleForceField attractionParticleForceField;
public Text attractionParticleForceFieldRadiusText;
public Text attractionParticleForceFieldMaxForceText;
public Text attractionParticleForceFieldArrivalRadiusText;
public Text attractionParticleForceFieldArrivedRadiusText;
public Text attractionParticleForceFieldPositionTextX;
public Text attractionParticleForceFieldPositionTextY;
public Text attractionParticleForceFieldPositionTextZ;
public Slider attractionParticleForceFieldRadiusSlider;
public Slider attractionParticleForceFieldMaxForceSlider;
public Slider attractionParticleForceFieldArrivalRadiusSlider;
public Slider attractionParticleForceFieldArrivedRadiusSlider;
public Slider attractionParticleForceFieldPositionSliderX;
public Slider attractionParticleForceFieldPositionSliderY;
public Slider attractionParticleForceFieldPositionSliderZ;
[Header("Vortex Particle Force Field Settings")]
public VortexParticleForceField vortexParticleForceField;
public Text vortexParticleForceFieldRadiusText;
public Text vortexParticleForceFieldMaxForceText;
public Text vortexParticleForceFieldRotationTextX;
public Text vortexParticleForceFieldRotationTextY;
public Text vortexParticleForceFieldRotationTextZ;
public Text vortexParticleForceFieldPositionTextX;
public Text vortexParticleForceFieldPositionTextY;
public Text vortexParticleForceFieldPositionTextZ;
public Slider vortexParticleForceFieldRadiusSlider;
public Slider vortexParticleForceFieldMaxForceSlider;
public Slider vortexParticleForceFieldRotationSliderX;
public Slider vortexParticleForceFieldRotationSliderY;
public Slider vortexParticleForceFieldRotationSliderZ;
public Slider vortexParticleForceFieldPositionSliderX;
public Slider vortexParticleForceFieldPositionSliderY;
public Slider vortexParticleForceFieldPositionSliderZ;
void Start()
{
// Overview.
if (postProcessing)
{
postProcessingToggle.isOn = postProcessing.enabled;
}
// Particle system settings.
particleSystemMainModule = particleSystem.main;
particleSystemEmissionModule = particleSystem.emission;
maxParticlesSlider.value = particleSystemMainModule.maxParticles;
particlesPerSecondSlider.value = particleSystemEmissionModule.rateOverTime.constant;
maxParticlesText.text = "Max Particles: " + maxParticlesSlider.value;
particlesPerSecondText.text = "Particles Per Second: " + particlesPerSecondSlider.value;
// Attraction particle force field settings.
attractionParticleForceFieldRadiusSlider.value = attractionParticleForceField.radius;
attractionParticleForceFieldMaxForceSlider.value = attractionParticleForceField.force;
attractionParticleForceFieldArrivalRadiusSlider.value = attractionParticleForceField.arrivalRadius;
attractionParticleForceFieldArrivedRadiusSlider.value = attractionParticleForceField.arrivedRadius;
Vector3 attractionParticleForceFieldPosition = attractionParticleForceField.transform.position;
attractionParticleForceFieldPositionSliderX.value = attractionParticleForceFieldPosition.x;
attractionParticleForceFieldPositionSliderY.value = attractionParticleForceFieldPosition.y;
attractionParticleForceFieldPositionSliderZ.value = attractionParticleForceFieldPosition.z;
attractionParticleForceFieldRadiusText.text = "Radius: " + attractionParticleForceFieldRadiusSlider.value;
attractionParticleForceFieldMaxForceText.text = "Max Force: " + attractionParticleForceFieldMaxForceSlider.value;
attractionParticleForceFieldArrivalRadiusText.text = "Arrival Radius: " + attractionParticleForceFieldArrivalRadiusSlider.value;
attractionParticleForceFieldArrivedRadiusText.text = "Arrived Radius: " + attractionParticleForceFieldArrivedRadiusSlider.value;
attractionParticleForceFieldPositionTextX.text = "Position X: " + attractionParticleForceFieldPositionSliderX.value;
attractionParticleForceFieldPositionTextY.text = "Position Y: " + attractionParticleForceFieldPositionSliderY.value;
attractionParticleForceFieldPositionTextZ.text = "Position Z: " + attractionParticleForceFieldPositionSliderZ.value;
// Vortex particle force field settings.
vortexParticleForceFieldRadiusSlider.value = vortexParticleForceField.radius;
vortexParticleForceFieldMaxForceSlider.value = vortexParticleForceField.force;
Vector3 vortexParticleForceFieldRotation = vortexParticleForceField.transform.eulerAngles;
vortexParticleForceFieldRotationSliderX.value = vortexParticleForceFieldRotation.x;
vortexParticleForceFieldRotationSliderY.value = vortexParticleForceFieldRotation.y;
vortexParticleForceFieldRotationSliderZ.value = vortexParticleForceFieldRotation.z;
Vector3 vortexParticleForceFieldPosition = vortexParticleForceField.transform.position;
vortexParticleForceFieldPositionSliderX.value = vortexParticleForceFieldPosition.x;
vortexParticleForceFieldPositionSliderY.value = vortexParticleForceFieldPosition.y;
vortexParticleForceFieldPositionSliderZ.value = vortexParticleForceFieldPosition.z;
vortexParticleForceFieldRadiusText.text = "Radius: " + vortexParticleForceFieldRadiusSlider.value;
vortexParticleForceFieldMaxForceText.text = "Max Force: " + vortexParticleForceFieldMaxForceSlider.value;
vortexParticleForceFieldRotationTextX.text = "Rotation X: " + vortexParticleForceFieldRotationSliderX.value;
vortexParticleForceFieldRotationTextY.text = "Rotation Y: " + vortexParticleForceFieldRotationSliderY.value;
vortexParticleForceFieldRotationTextZ.text = "Rotation Z: " + vortexParticleForceFieldRotationSliderZ.value;
vortexParticleForceFieldPositionTextX.text = "Position X: " + vortexParticleForceFieldPositionSliderX.value;
vortexParticleForceFieldPositionTextY.text = "Position Y: " + vortexParticleForceFieldPositionSliderY.value;
vortexParticleForceFieldPositionTextZ.text = "Position Z: " + vortexParticleForceFieldPositionSliderZ.value;
}
void Update()
{
// Overview.
FPSText.text = "FPS: " + 1.0f / Time.deltaTime;
particleCountText.text = "Particle Count: " + particleSystem.particleCount;
}
public void ReloadScene()
{
SceneManager.LoadScene(SceneManager.GetActiveScene().buildIndex);
}
// Particle system settings.
public void SetMaxParticles(float value)
{
particleSystemMainModule.maxParticles = (int)value;
maxParticlesText.text = "Max Particles: " + value;
}
public void SetParticleEmissionPerSecond(float value)
{
particleSystemEmissionModule.rateOverTime = value;
particlesPerSecondText.text = "Particles Per Second: " + value;
}
// Attraction particle force field settings.
public void SetAttractionParticleForceFieldRadius(float value)
{
attractionParticleForceField.radius = value;
attractionParticleForceFieldRadiusText.text = "Radius: " + value;
}
public void SetAttractionParticleForceFieldMaxForce(float value)
{
attractionParticleForceField.force = value;
attractionParticleForceFieldMaxForceText.text = "Max Force: " + value;
}
public void SetAttractionParticleForceFieldArrivalRadius(float value)
{
attractionParticleForceField.arrivalRadius = value;
attractionParticleForceFieldArrivalRadiusText.text = "Arrival Radius: " + value;
}
public void SetAttractionParticleForceFieldArrivedRadius(float value)
{
attractionParticleForceField.arrivedRadius = value;
attractionParticleForceFieldArrivedRadiusText.text = "Arrived Radius: " + value;
}
public void SetAttractionParticleForceFieldPositionX(float value)
{
Vector3 position = attractionParticleForceField.transform.position;
position.x = value;
attractionParticleForceField.transform.position = position;
attractionParticleForceFieldPositionTextX.text = "Position X: " + value;
}
public void SetAttractionParticleForceFieldPositionY(float value)
{
Vector3 position = attractionParticleForceField.transform.position;
position.y = value;
attractionParticleForceField.transform.position = position;
attractionParticleForceFieldPositionTextY.text = "Position Y: " + value;
}
public void SetAttractionParticleForceFieldPositionZ(float value)
{
Vector3 position = attractionParticleForceField.transform.position;
position.z = value;
attractionParticleForceField.transform.position = position;
attractionParticleForceFieldPositionTextZ.text = "Position Z: " + value;
}
// Vortex particle force field settings.
public void SetVortexParticleForceFieldRadius(float value)
{
vortexParticleForceField.radius = value;
vortexParticleForceFieldRadiusText.text = "Radius: " + value;
}
public void SetVortexParticleForceFieldMaxForce(float value)
{
vortexParticleForceField.force = value;
vortexParticleForceFieldMaxForceText.text = "Max Force: " + value;
}
public void SetVortexParticleForceFieldRotationX(float value)
{
Vector3 rotation = vortexParticleForceField.transform.eulerAngles;
rotation.x = value;
vortexParticleForceField.transform.eulerAngles = rotation;
vortexParticleForceFieldRotationTextX.text = "Rotation X: " + value;
}
public void SetVortexParticleForceFieldRotationY(float value)
{
Vector3 rotation = vortexParticleForceField.transform.eulerAngles;
rotation.y = value;
vortexParticleForceField.transform.eulerAngles = rotation;
vortexParticleForceFieldRotationTextY.text = "Rotation Y: " + value;
}
public void SetVortexParticleForceFieldRotationZ(float value)
{
Vector3 rotation = vortexParticleForceField.transform.eulerAngles;
rotation.z = value;
vortexParticleForceField.transform.eulerAngles = rotation;
vortexParticleForceFieldRotationTextZ.text = "Rotation Z: " + value;
}
public void SetVortexParticleForceFieldPositionX(float value)
{
Vector3 position = vortexParticleForceField.transform.position;
position.x = value;
vortexParticleForceField.transform.position = position;
vortexParticleForceFieldPositionTextX.text = "Position X: " + value;
}
public void SetVortexParticleForceFieldPositionY(float value)
{
Vector3 position = vortexParticleForceField.transform.position;
position.y = value;
vortexParticleForceField.transform.position = position;
vortexParticleForceFieldPositionTextY.text = "Position Y: " + value;
}
public void SetVortexParticleForceFieldPositionZ(float value)
{
Vector3 position = vortexParticleForceField.transform.position;
position.z = value;
vortexParticleForceField.transform.position = position;
vortexParticleForceFieldPositionTextZ.text = "Position Z: " + value;
}
}

View File

@@ -0,0 +1,12 @@
fileFormatVersion: 2
guid: 250820ec8673f9549acc97449bee156c
timeCreated: 1508398214
licenseType: Store
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,50 @@
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class ParticleForceFieldsDemo_CameraRig : MonoBehaviour
{
public Transform pivot;
Vector3 targetRotation;
[Range(0.0f, 90.0f)]
public float rotationLimit = 90.0f;
public float rotationSpeed = 2.0f;
public float rotationLerpSpeed = 4.0f;
Vector3 startRotation;
void Start()
{
startRotation = pivot.localEulerAngles;
targetRotation = startRotation;
}
void Update()
{
float horizontal = Input.GetAxis("Horizontal");
float vertical = Input.GetAxis("Vertical");
if (Input.GetKeyDown(KeyCode.R))
{
targetRotation = startRotation;
}
horizontal *= rotationSpeed;
vertical *= rotationSpeed;
targetRotation.y += horizontal;
targetRotation.x += vertical;
targetRotation.x = Mathf.Clamp(targetRotation.x, -rotationLimit, rotationLimit);
targetRotation.y = Mathf.Clamp(targetRotation.y, -rotationLimit, rotationLimit);
Vector3 currentRotation = pivot.localEulerAngles;
currentRotation.x = Mathf.LerpAngle(currentRotation.x, targetRotation.x, Time.deltaTime * rotationLerpSpeed);
currentRotation.y = Mathf.LerpAngle(currentRotation.y, targetRotation.y, Time.deltaTime * rotationLerpSpeed);
pivot.localEulerAngles = currentRotation;
}
}

View File

@@ -0,0 +1,12 @@
fileFormatVersion: 2
guid: f5219d102a973a645a4b97512415c865
timeCreated: 1508405059
licenseType: Store
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,9 @@
fileFormatVersion: 2
guid: c6b070ddda83ff346a0c6789971e618a
folderAsset: yes
timeCreated: 1485465640
licenseType: Store
DefaultImporter:
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,161 @@
// =================================
// Namespaces.
// =================================
using UnityEngine;
// =================================
// Define namespace.
// =================================
namespace MirzaBeig
{
namespace Scripting
{
namespace Effects
{
// =================================
// Classes.
// =================================
[AddComponentMenu("Effects/Particle Force Fields/Attraction Particle Force Field")]
public class AttractionParticleForceField : ParticleForceField
{
// =================================
// Nested classes and structures.
// =================================
// ...
// =================================
// Variables.
// =================================
// ...
[Header("ForceField Controls")]
[Tooltip("Tether force based on linear inverse particle distance to force field center.")]
public float arrivalRadius = 1.0f;
[Tooltip("Dead zone from force field center in which no additional force is applied.")]
public float arrivedRadius = 0.5f;
float arrivalRadiusSqr;
float arrivedRadiusSqr;
// =================================
// Functions.
// =================================
// ...
protected override void Awake()
{
base.Awake();
}
// ...
protected override void Start()
{
base.Start();
}
// ...
protected override void Update()
{
base.Update();
}
// ...
protected override void LateUpdate()
{
float uniformTransformScale = transform.lossyScale.x;
arrivalRadiusSqr = (arrivalRadius * arrivalRadius) * uniformTransformScale;
arrivedRadiusSqr = (arrivedRadius * arrivedRadius) * uniformTransformScale;
// ...
base.LateUpdate();
}
// ...
protected override Vector3 GetForce()
{
Vector3 force;
if (parameters.distanceToForceFieldCenterSqr < arrivedRadiusSqr)
{
force.x = 0.0f;
force.y = 0.0f;
force.z = 0.0f;
}
else if (parameters.distanceToForceFieldCenterSqr < arrivalRadiusSqr)
{
float inverseArrivalScaleNormalized = 1.0f - (parameters.distanceToForceFieldCenterSqr / arrivalRadiusSqr);
force = Vector3.Normalize(parameters.scaledDirectionToForceFieldCenter) * inverseArrivalScaleNormalized;
}
else
{
force = Vector3.Normalize(parameters.scaledDirectionToForceFieldCenter);
}
return force;
}
// ...
protected override void OnDrawGizmosSelected()
{
if (enabled)
{
base.OnDrawGizmosSelected();
// ...
float uniformTransformScale = transform.lossyScale.x;
float arrivalRadius = this.arrivalRadius * uniformTransformScale;
float arrivedRadius = this.arrivedRadius * uniformTransformScale;
Vector3 offsetCenter = transform.position + center;
Gizmos.color = Color.yellow;
Gizmos.DrawWireSphere(offsetCenter, arrivalRadius);
Gizmos.color = Color.red;
Gizmos.DrawWireSphere(offsetCenter, arrivedRadius);
//Gizmos.color = Color.white;
//Gizmos.DrawLine(currentParticleSystem.transform.position, offsetCenter);
}
}
// =================================
// End functions.
// =================================
}
// =================================
// End namespace.
// =================================
}
}
}
// =================================
// --END-- //
// =================================

View File

@@ -0,0 +1,12 @@
fileFormatVersion: 2
guid: e1fdf750d337aed4f8a30771049b5559
timeCreated: 1470567812
licenseType: Store
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,12 @@
fileFormatVersion: 2
guid: b44853b525f9caf40bab3434705bc51e
timeCreated: 1458196122
licenseType: Store
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,570 @@
// =================================
// Namespaces.
// =================================
using UnityEngine;
using System.Collections.Generic;
// =================================
// Define namespace.
// =================================
namespace MirzaBeig
{
namespace Scripting
{
namespace Effects
{
// =================================
// Classes.
// =================================
public abstract class ParticleForceField : MonoBehaviour
{
// =================================
// Nested classes and structures.
// =================================
// ...
protected struct GetForceParameters
{
public float distanceToForceFieldCenterSqr;
public Vector3 scaledDirectionToForceFieldCenter;
public Vector3 particlePosition;
}
// =================================
// Variables.
// =================================
// ...
[Header("Common Controls")]
[Tooltip("Force field spherical range.")]
public float radius = Mathf.Infinity;
[Tooltip("Maximum baseline force.")]
public float force = 5.0f;
[Tooltip("Internal force field position offset.")]
public Vector3 center = Vector3.zero;
public float scaledRadius
{
get
{
return radius * transform.lossyScale.x;
}
}
float _radius;
float radiusSqr;
Vector3 transformPosition;
float[] particleSystemExternalForcesMultipliers;
[Tooltip("Force scale as determined by distance to individual particles.")]
public AnimationCurve forceOverDistance = new AnimationCurve(
new Keyframe(0.0f, 1.0f),
new Keyframe(1.0f, 1.0f)
);
// If (attached to a particle system): forces will be LOCAL.
// Else if (attached to a particle system): forces will be SELECTIVE.
// Else: forces will be GLOBAL.
new ParticleSystem particleSystem;
[Tooltip(
"If nothing no particle systems are assigned, this force field will operate globally on ALL particle systems in the scene (NOT recommended).\n\n" +
"If attached to a particle system, the force field will operate only on that system.\n\n" +
"If specific particle systems are assigned, then the force field will operate on those systems only, even if attached to a particle system.")]
public List<ParticleSystem> _particleSystems;
int particleSystemsCount;
// All required particle systems that will actually be used.
List<ParticleSystem> particleSystems = new List<ParticleSystem>();
// Particles in each system.
// Second dimension initialized to max particle count
// and not modified unless max particle count for that system changes.
// Prevents allocations each frame.
ParticleSystem.Particle[][] particleSystemParticles;
ParticleSystem.MainModule[] particleSystemMainModules;
Renderer[] particleSystemRenderers;
// ^I could also just put the system and the module in a struct and make a 2D array
// instead of having a seperate array for the modules.
// Current iteration of the particle systems when looping through all of them.
// Useful to derived classes (like for the vortex particle affector).
protected ParticleSystem currentParticleSystem;
// Parameters used by derived force classes.
protected GetForceParameters parameters;
// Update even when entire particle system is invisible?
// Default: FALSE -> if all particles are invisible/offscreen, update will not execute.
[Tooltip(
"If TRUE, update even if target particle system(s) are invisible/offscreen.\n\n" +
"If FALSE, update only if particles of the target system(s) are visible/onscreen.")]
public bool alwaysUpdate = false;
// =================================
// Functions.
// =================================
// ...
protected virtual void Awake()
{
}
// ...
protected virtual void Start()
{
particleSystem = GetComponent<ParticleSystem>();
}
// Called once per particle system, before entering second loop for its particles.
// Used for setting up based on particle system-specific data.
protected virtual void PerParticleSystemSetup()
{
}
// Direction is NOT normalized.
protected virtual Vector3 GetForce()
{
return Vector3.zero;
}
// ...
protected virtual void Update()
{
}
// Add/remove from public list of particles being managed.
// Remember that adding specific systems will override all
// other contexts (global and pure local).
// Duplicates are not checked (intentionally).
public void AddParticleSystem(ParticleSystem particleSystem)
{
_particleSystems.Add(particleSystem);
}
public void RemoveParticleSystem(ParticleSystem particleSystem)
{
_particleSystems.Remove(particleSystem);
}
// ...
protected virtual void LateUpdate()
{
_radius = scaledRadius;
radiusSqr = _radius * _radius;
transformPosition = transform.position + center;
// SELECTIVE.
// If manually assigned a set of systems, use those no matter what.
if (_particleSystems.Count != 0)
{
// If editor array size changed, clear and add again.
if (particleSystems.Count != _particleSystems.Count)
{
particleSystems.Clear();
particleSystems.AddRange(_particleSystems);
}
// Else if array size is the same, then re-assign from
// the editor array. I do this in case the elements are different
// even though the size is the same.
else
{
for (int i = 0; i < _particleSystems.Count; i++)
{
particleSystems[i] = _particleSystems[i];
}
}
}
// LOCAL.
// Else if attached to particle system, use only that.
// Obviously, this will only happen if there are no systems specified in the array.
else if (particleSystem)
{
// If just one element, assign as local PS component.
if (particleSystems.Count == 1)
{
particleSystems[0] = particleSystem;
}
// Else, clear entire array and add only the one.
else
{
particleSystems.Clear();
particleSystems.Add(particleSystem);
}
}
// GLOBAL.
// Else, take all the ones from the entire scene.
// This is the most expensive since it searches the entire scene
// and also requires an allocation for every frame due to not knowing
// if the particle systems are all the same from the last frame unless
// I had a list to compare to from last frame. In that case, I'm not sure
// if the performance would be better or worse. Do a test later?
else
{
particleSystems.Clear();
particleSystems.AddRange(FindObjectsOfType<ParticleSystem>());
}
parameters = new GetForceParameters();
particleSystemsCount = particleSystems.Count;
// If first frame (array is null) or length is less than the number of systems, initialize size of array.
// I never shrink the array. Not sure if that's potentially super bad? I could always throw in a public
// bool as an option to allow shrinking since there's a performance benefit for each, but depends on the
// implementation case.
if (particleSystemParticles == null || particleSystemParticles.Length < particleSystemsCount)
{
particleSystemParticles = new ParticleSystem.Particle[particleSystemsCount][];
particleSystemMainModules = new ParticleSystem.MainModule[particleSystemsCount];
particleSystemRenderers = new Renderer[particleSystemsCount];
particleSystemExternalForcesMultipliers = new float[particleSystemsCount];
for (int i = 0; i < particleSystemsCount; i++)
{
particleSystemMainModules[i] = particleSystems[i].main;
particleSystemRenderers[i] = particleSystems[i].GetComponent<Renderer>();
particleSystemExternalForcesMultipliers[i] = particleSystems[i].externalForces.multiplier;
}
}
for (int i = 0; i < particleSystemsCount; i++)
{
if (!particleSystemRenderers[i].isVisible && !alwaysUpdate)
{
continue;
}
int maxParticles = particleSystemMainModules[i].maxParticles;
// Force delta time should reflect particle system delta time mode.
float forceDeltaTime = force * (particleSystemMainModules[i].useUnscaledTime ? Time.unscaledDeltaTime : Time.deltaTime);
if (particleSystemParticles[i] == null || particleSystemParticles[i].Length < maxParticles)
{
particleSystemParticles[i] = new ParticleSystem.Particle[maxParticles];
}
currentParticleSystem = particleSystems[i];
PerParticleSystemSetup();
int particleCount = currentParticleSystem.GetParticles(particleSystemParticles[i]);
ParticleSystemSimulationSpace simulationSpace = particleSystemMainModules[i].simulationSpace;
ParticleSystemScalingMode scalingMode = particleSystemMainModules[i].scalingMode;
// I could also store the transforms in an array similar to what I do with modules.
// Or, put all of those together into a struct and make an array out of that since
// they'll always be assigned/updated at the same time.
Transform currentParticleSystemTransform = currentParticleSystem.transform;
Transform customSimulationSpaceTransform = particleSystemMainModules[i].customSimulationSpace;
// If in world space, there's no need to do any of the extra calculations... simplify the loop!
if (simulationSpace == ParticleSystemSimulationSpace.World)
{
for (int j = 0; j < particleCount; j++)
{
parameters.particlePosition = particleSystemParticles[i][j].position;
parameters.scaledDirectionToForceFieldCenter.x = transformPosition.x - parameters.particlePosition.x;
parameters.scaledDirectionToForceFieldCenter.y = transformPosition.y - parameters.particlePosition.y;
parameters.scaledDirectionToForceFieldCenter.z = transformPosition.z - parameters.particlePosition.z;
parameters.distanceToForceFieldCenterSqr = parameters.scaledDirectionToForceFieldCenter.sqrMagnitude;
if (parameters.distanceToForceFieldCenterSqr < radiusSqr)
{
float distanceToCenterNormalized = parameters.distanceToForceFieldCenterSqr / radiusSqr;
float distanceScale = forceOverDistance.Evaluate(distanceToCenterNormalized);
Vector3 force = GetForce();
float forceScale = (forceDeltaTime * distanceScale) * particleSystemExternalForcesMultipliers[i];
force.x *= forceScale;
force.y *= forceScale;
force.z *= forceScale;
Vector3 particleVelocity = particleSystemParticles[i][j].velocity;
particleVelocity.x += force.x;
particleVelocity.y += force.y;
particleVelocity.z += force.z;
particleSystemParticles[i][j].velocity = particleVelocity;
}
}
}
else
{
Vector3 particleSystemPosition = Vector3.zero;
Quaternion particleSystemRotation = Quaternion.identity;
Vector3 particleSystemLocalScale = Vector3.one;
Transform simulationSpaceTransform = currentParticleSystemTransform;
switch (simulationSpace)
{
case ParticleSystemSimulationSpace.Local:
{
particleSystemPosition = simulationSpaceTransform.position;
particleSystemRotation = simulationSpaceTransform.rotation;
particleSystemLocalScale = simulationSpaceTransform.localScale;
break;
}
case ParticleSystemSimulationSpace.Custom:
{
simulationSpaceTransform = customSimulationSpaceTransform;
particleSystemPosition = simulationSpaceTransform.position;
particleSystemRotation = simulationSpaceTransform.rotation;
particleSystemLocalScale = simulationSpaceTransform.localScale;
break;
}
default:
{
throw new System.NotSupportedException(
string.Format("Unsupported scaling mode '{0}'.", simulationSpace));
}
}
for (int j = 0; j < particleCount; j++)
{
parameters.particlePosition = particleSystemParticles[i][j].position;
switch (simulationSpace)
{
case ParticleSystemSimulationSpace.Local:
case ParticleSystemSimulationSpace.Custom:
{
switch (scalingMode)
{
case ParticleSystemScalingMode.Hierarchy:
{
parameters.particlePosition = simulationSpaceTransform.TransformPoint(particleSystemParticles[i][j].position);
break;
}
case ParticleSystemScalingMode.Local:
{
// Order is important.
parameters.particlePosition = Vector3.Scale(parameters.particlePosition, particleSystemLocalScale);
parameters.particlePosition = particleSystemRotation * parameters.particlePosition;
parameters.particlePosition = parameters.particlePosition + particleSystemPosition;
break;
}
case ParticleSystemScalingMode.Shape:
{
parameters.particlePosition = particleSystemRotation * parameters.particlePosition;
parameters.particlePosition = parameters.particlePosition + particleSystemPosition;
break;
}
default:
{
throw new System.NotSupportedException(
string.Format("Unsupported scaling mode '{0}'.", scalingMode));
}
}
break;
}
}
parameters.scaledDirectionToForceFieldCenter.x = transformPosition.x - parameters.particlePosition.x;
parameters.scaledDirectionToForceFieldCenter.y = transformPosition.y - parameters.particlePosition.y;
parameters.scaledDirectionToForceFieldCenter.z = transformPosition.z - parameters.particlePosition.z;
parameters.distanceToForceFieldCenterSqr = parameters.scaledDirectionToForceFieldCenter.sqrMagnitude;
//particleSystemParticles[i][j].velocity += forceDeltaTime * Vector3.Normalize(parameters.scaledDirectionToForceFieldCenter);
if (parameters.distanceToForceFieldCenterSqr < radiusSqr)
{
// 0.0f -> 0.99...f;
float distanceToCenterNormalized = parameters.distanceToForceFieldCenterSqr / radiusSqr;
// Evaluating a curve within a loop which is very likely to exceed a few thousand
// iterations produces a noticeable FPS drop (around minus 2 - 5). Might be a worthwhile
// optimization to check outside all loops if the curve is constant (all keyframes same value),
// and then run a different block of code if true that uses that value as a stored float without
// having to call Evaluate(t).
float distanceScale = forceOverDistance.Evaluate(distanceToCenterNormalized);
// Expanded vector operations for optimization. I think this is already done by
// the compiler, but it's nice to have for the editor anyway.
Vector3 force = GetForce();
float forceScale = (forceDeltaTime * distanceScale) * particleSystemExternalForcesMultipliers[i];
force.x *= forceScale;
force.y *= forceScale;
force.z *= forceScale;
switch (simulationSpace)
{
case ParticleSystemSimulationSpace.Local:
case ParticleSystemSimulationSpace.Custom:
{
switch (scalingMode)
{
case ParticleSystemScalingMode.Hierarchy:
{
force = simulationSpaceTransform.InverseTransformVector(force);
break;
}
case ParticleSystemScalingMode.Local:
{
// Order is important.
// Notice how rotation and scale orders are reversed.
force = Quaternion.Inverse(particleSystemRotation) * force;
force = Vector3.Scale(force, new Vector3(
1.0f / particleSystemLocalScale.x,
1.0f / particleSystemLocalScale.y,
1.0f / particleSystemLocalScale.z));
break;
}
case ParticleSystemScalingMode.Shape:
{
force = Quaternion.Inverse(particleSystemRotation) * force;
break;
}
// This would technically never execute since it's checked earlier (above).
default:
{
throw new System.NotSupportedException(
string.Format("Unsupported scaling mode '{0}'.", scalingMode));
}
}
break;
}
}
Vector3 particleVelocity = particleSystemParticles[i][j].velocity;
particleVelocity.x += force.x;
particleVelocity.y += force.y;
particleVelocity.z += force.z;
particleSystemParticles[i][j].velocity = particleVelocity;
}
}
}
currentParticleSystem.SetParticles(particleSystemParticles[i], particleCount);
}
}
// ...
void OnApplicationQuit()
{
}
// ...
protected virtual void OnDrawGizmosSelected()
{
Gizmos.color = Color.green;
Gizmos.DrawWireSphere(transform.position + center, scaledRadius);
}
// =================================
// End functions.
// =================================
}
// =================================
// End namespace.
// =================================
}
}
}
// =================================
// --END-- //
// =================================

View File

@@ -0,0 +1,12 @@
fileFormatVersion: 2
guid: 438d3a992ed592445b2ca9cf747b6ffc
timeCreated: 1470567813
licenseType: Store
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,275 @@
// =================================
// Namespaces.
// =================================
using UnityEngine;
// =================================
// Define namespace.
// =================================
namespace MirzaBeig
{
namespace Scripting
{
namespace Effects
{
// =================================
// Classes.
// =================================
[AddComponentMenu("Effects/Particle Force Fields/Turbulence Particle Force Field")]
public class TurbulenceParticleForceField : ParticleForceField
{
// =================================
// Nested classes and structures.
// =================================
// ...
public enum NoiseType
{
PseudoPerlin,
Perlin,
Simplex,
OctavePerlin,
OctaveSimplex
}
// =================================
// Variables.
// =================================
// ...
[Header("ForceField Controls")]
[Tooltip("Noise texture mutation speed.")]
public float scrollSpeed = 1.0f;
[Range(0.0f, 8.0f)]
[Tooltip("Noise texture detail amplifier.")]
public float frequency = 1.0f;
public NoiseType noiseType = NoiseType.Perlin;
// ...
[Header("Octave Variant-Only Controls")]
[Range(1, 8)]
[Tooltip("Overlapping noise iterations. 1 = no additional iterations.")]
public int octaves = 1;
[Range(0.0f, 4.0f)]
[Tooltip("Frequency scale per-octave. Can be used to change the overlap every iteration.")]
public float octaveMultiplier = 0.5f;
[Range(0.0f, 1.0f)]
[Tooltip("Amplitude scale per-octave. Can be used to change the overlap every iteration.")]
public float octaveScale = 2.0f;
float time;
// Noise2 start offsets.
float randomX;
float randomY;
float randomZ;
// Final offset.
float offsetX;
float offsetY;
float offsetZ;
// =================================
// Functions.
// =================================
// ...
protected override void Awake()
{
base.Awake();
}
// ...
protected override void Start()
{
base.Start();
// ...
randomX = Random.Range(-32.0f, 32.0f);
randomY = Random.Range(-32.0f, 32.0f);
randomZ = Random.Range(-32.0f, 32.0f);
}
// ...
protected override void Update()
{
time = Time.time;
// ...
base.Update();
}
// ...
protected override void LateUpdate()
{
offsetX = (time * scrollSpeed) + randomX;
offsetY = (time * scrollSpeed) + randomY;
offsetZ = (time * scrollSpeed) + randomZ;
// ...
base.LateUpdate();
}
// ...
protected override Vector3 GetForce()
{
// I could also pre-multiply the frequency, but
// all the octave variants also use frequency
// within themselves, so it would cause redundant
// multiplication.
float xX = parameters.particlePosition.x + offsetX;
float yX = parameters.particlePosition.y + offsetX;
float zX = parameters.particlePosition.z + offsetX;
float xY = parameters.particlePosition.x + offsetY;
float yY = parameters.particlePosition.y + offsetY;
float zY = parameters.particlePosition.z + offsetY;
float xZ = parameters.particlePosition.x + offsetZ;
float yZ = parameters.particlePosition.y + offsetZ;
float zZ = parameters.particlePosition.z + offsetZ;
Vector3 force;
switch (noiseType)
{
case NoiseType.PseudoPerlin:
{
// This isn't really right, but... it gives believable-enough results.
// It's also much faster than real perlin noise.
// It works well where you don't have to animate a large field where
// the repeating pattern would otherwise be easily seen.
// Examples of good uses: smoke trail particle turbulence.
// Example of bad uses: particle box simulating waves or something...
float noiseX = Mathf.PerlinNoise(xX * frequency, yY * frequency);
float noiseY = Mathf.PerlinNoise(xX * frequency, zY * frequency);
float noiseZ = Mathf.PerlinNoise(xX * frequency, xY * frequency);
noiseX = Mathf.Lerp(-1.0f, 1.0f, noiseX);
noiseY = Mathf.Lerp(-1.0f, 1.0f, noiseY);
noiseZ = Mathf.Lerp(-1.0f, 1.0f, noiseZ);
Vector3 forceX = (Vector3.right * noiseX);
Vector3 forceY = (Vector3.up * noiseY);
Vector3 forceZ = (Vector3.forward * noiseZ);
force = forceX + forceY + forceZ;
break;
}
// ...
default:
case NoiseType.Perlin:
{
force.x = Noise2.perlin(xX * frequency, yX * frequency, zX * frequency);
force.y = Noise2.perlin(xY * frequency, yY * frequency, zY * frequency);
force.z = Noise2.perlin(xZ * frequency, yZ * frequency, zZ * frequency);
return force;
}
// ...
case NoiseType.Simplex:
{
force.x = Noise2.simplex(xX * frequency, yX * frequency, zX * frequency);
force.y = Noise2.simplex(xY * frequency, yY * frequency, zY * frequency);
force.z = Noise2.simplex(xZ * frequency, yZ * frequency, zZ * frequency);
break;
}
// ...
case NoiseType.OctavePerlin:
{
force.x = Noise2.octavePerlin(xX, yX, zX, frequency, octaves, octaveMultiplier, octaveScale);
force.y = Noise2.octavePerlin(xY, yY, zY, frequency, octaves, octaveMultiplier, octaveScale);
force.z = Noise2.octavePerlin(xZ, yZ, zZ, frequency, octaves, octaveMultiplier, octaveScale);
break;
}
case NoiseType.OctaveSimplex:
{
force.x = Noise2.octaveSimplex(xX, yX, zX, frequency, octaves, octaveMultiplier, octaveScale);
force.y = Noise2.octaveSimplex(xY, yY, zY, frequency, octaves, octaveMultiplier, octaveScale);
force.z = Noise2.octaveSimplex(xZ, yZ, zZ, frequency, octaves, octaveMultiplier, octaveScale);
break;
}
}
return force;
}
// ...
protected override void OnDrawGizmosSelected()
{
if (enabled)
{
base.OnDrawGizmosSelected();
}
}
// =================================
// End functions.
// =================================
}
// =================================
// End namespace.
// =================================
}
}
}
// =================================
// --END-- //
// =================================

View File

@@ -0,0 +1,12 @@
fileFormatVersion: 2
guid: 7e733210563cdf8419c597d30703d906
timeCreated: 1470567813
licenseType: Store
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,166 @@
// =================================
// Namespaces.
// =================================
using UnityEngine;
// =================================
// Define namespace.
// =================================
namespace MirzaBeig
{
namespace Scripting
{
namespace Effects
{
// =================================
// Classes.
// =================================
[AddComponentMenu("Effects/Particle Force Fields/Vortex Particle Force Field")]
public class VortexParticleForceField : ParticleForceField
{
// =================================
// Nested classes and structures.
// =================================
// ...
// =================================
// Variables.
// =================================
// ...
Vector3 axisOfRotation;
[Header("ForceField Controls")]
[Tooltip(
"Internal offset for the axis of rotation.\n\n" +
"Useful if the force field and particle system are on the same game object, and you need a seperate rotation for the system, and the affector, but don't want to make the two different game objects.")]
public Vector3 axisOfRotationOffset = Vector3.zero;
// =================================
// Functions.
// =================================
// ...
protected override void Awake()
{
base.Awake();
}
// ...
protected override void Start()
{
base.Start();
}
// ...
protected override void Update()
{
base.Update();
}
// ...
protected override void LateUpdate()
{
base.LateUpdate();
}
// ...
void UpdateAxisOfRotation()
{
axisOfRotation = Quaternion.Euler(axisOfRotationOffset) * transform.up;
}
// ...
protected override void PerParticleSystemSetup()
{
UpdateAxisOfRotation();
}
// ...
protected override Vector3 GetForce()
{
// With no rotation, looking at the PS with the vortex down the Z axis, you may
// think it's spinning the wrong way because it's counter-clockwise. But it's actually correct...
// Because if you were to look up aligned with the up-axis of the vortex, you'd see it spinning
// clockwise. And if that up was inverted (you looked down at the vortex from above), then it would
// be spinning counter-clockwise since now the vector of rotation is point at you, not away from you.
// I can't believe I almost mixed that up by adding a negative (-) in front of the return.
return Vector3.Normalize(Vector3.Cross(axisOfRotation, parameters.scaledDirectionToForceFieldCenter));
}
// ...
protected override void OnDrawGizmosSelected()
{
if (enabled)
{
base.OnDrawGizmosSelected();
// ...
Gizmos.color = Color.red;
// When not playing, I don't have a reference to the specific particle system,
// so just use the default method of showing the axis of rotation (which may be wrong).
// There's no easy way around this since I may have several particle systems being updated
// with a single vortex. It's just a visual guide anyways, so no big deal, I suppose.
Vector3 axisOfRotation;
if (Application.isPlaying && enabled)
{
UpdateAxisOfRotation();
axisOfRotation = this.axisOfRotation;
}
else
{
axisOfRotation = Quaternion.Euler(axisOfRotationOffset) * transform.up;
}
Vector3 offsetCenter = transform.position + center;
Gizmos.DrawLine(offsetCenter, offsetCenter + (axisOfRotation * scaledRadius));
}
}
// =================================
// End functions.
// =================================
}
// =================================
// End namespace.
// =================================
}
}
}
// =================================
// --END-- //
// =================================

View File

@@ -0,0 +1,12 @@
fileFormatVersion: 2
guid: 37b87b5be4beb0d4dab3058662d07b44
timeCreated: 1470567812
licenseType: Store
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,9 @@
fileFormatVersion: 2
guid: 5332e56ae936db64f96e78f1fd42fb10
folderAsset: yes
timeCreated: 1471472531
licenseType: Store
DefaultImporter:
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,9 @@
fileFormatVersion: 2
guid: e052bf39285577445af92b6e5cf93a94
folderAsset: yes
timeCreated: 1485465673
licenseType: Store
DefaultImporter:
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,166 @@
// =================================
// Namespaces.
// =================================
using UnityEngine;
using System.Collections.Generic;
// =================================
// Define namespace.
// =================================
namespace MirzaBeig
{
namespace Scripting
{
namespace Effects
{
// =================================
// Classes.
// =================================
//[ExecuteInEditMode]
[System.Serializable]
[RequireComponent(typeof(ParticleSystem))]
public class ParticleLights : MonoBehaviour
{
// =================================
// Nested classes and structures.
// =================================
// ...
// =================================
// Variables.
// =================================
// ...
ParticleSystem ps;
List<Light> lights = new List<Light>();
//public LightType type = LightType.Point;
public float scale = 2.0f;
[Range(0.0f, 8.0f)]
public float intensity = 8.0f;
public Color colour = Color.white;
[Range(0.0f, 1.0f)]
public float colourFromParticle = 1.0f;
public LightShadows shadows = LightShadows.None;
GameObject template;
// =================================
// Functions.
// =================================
// ...
void Awake()
{
}
// ...
void Start()
{
ps = GetComponent<ParticleSystem>();
template = new GameObject();
template.transform.SetParent(transform);
template.name = "Template";
}
// ...
void Update()
{
}
// ...
void LateUpdate()
{
ParticleSystem.Particle[] particles =
new ParticleSystem.Particle[ps.particleCount];
int numOfParticles = ps.GetParticles(particles);
if (lights.Count != numOfParticles)
{
for (int i = 0; i < lights.Count; i++)
{
Destroy(lights[i].gameObject);
}
lights.Clear();
for (int i = 0; i < numOfParticles; i++)
{
GameObject go = Instantiate(template, transform) as GameObject;
go.name = "- " + (i + 1).ToString();
lights.Add(go.AddComponent<Light>());
}
}
ParticleSystem.MainModule m = ps.main;
bool worldSpace = m.simulationSpace == ParticleSystemSimulationSpace.World;
for (int i = 0; i < numOfParticles; i++)
{
ParticleSystem.Particle p = particles[i];
Light light = lights[i];
//light.type = type;
//if (type == LightType.Spot)
//{
// light.transform.rotation = Quaternion.Euler(p.rotation3D);
//}
light.range = p.GetCurrentSize(ps) * scale;
light.color = Color.Lerp(colour, p.GetCurrentColor(ps), colourFromParticle);
light.intensity = intensity;
light.shadows = shadows;
light.transform.position = worldSpace ? p.position : ps.transform.TransformPoint(p.position);
}
}
// =================================
// End functions.
// =================================
}
// =================================
// End namespace.
// =================================
}
}
}
// =================================
// --END-- //
// =================================

View File

@@ -0,0 +1,12 @@
fileFormatVersion: 2
guid: f32496b72584aa54788fca63c858de5e
timeCreated: 1470567813
licenseType: Store
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,9 @@
fileFormatVersion: 2
guid: 14034914d0c5055478728ee6ebaccd5d
folderAsset: yes
timeCreated: 1485465588
licenseType: Store
DefaultImporter:
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,9 @@
fileFormatVersion: 2
guid: 5cc3d79fe4d65e94f9901f89ed53e8d2
folderAsset: yes
timeCreated: 1508486697
licenseType: Store
DefaultImporter:
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,78 @@
%YAML 1.1
%TAG !u! tag:unity3d.com,2011:
--- !u!21 &2100000
Material:
serializedVersion: 6
m_ObjectHideFlags: 0
m_PrefabParentObject: {fileID: 0}
m_PrefabInternal: {fileID: 0}
m_Name: Default Particle (Additive)
m_Shader: {fileID: 200, guid: 0000000000000000f000000000000000, type: 0}
m_ShaderKeywords:
m_LightmapFlags: 4
m_EnableInstancingVariants: 0
m_DoubleSidedGI: 0
m_CustomRenderQueue: -1
stringTagMap: {}
disabledShaderPasses: []
m_SavedProperties:
serializedVersion: 3
m_TexEnvs:
- _BumpMap:
m_Texture: {fileID: 0}
m_Scale: {x: 1, y: 1}
m_Offset: {x: 0, y: 0}
- _DetailAlbedoMap:
m_Texture: {fileID: 0}
m_Scale: {x: 1, y: 1}
m_Offset: {x: 0, y: 0}
- _DetailMask:
m_Texture: {fileID: 0}
m_Scale: {x: 1, y: 1}
m_Offset: {x: 0, y: 0}
- _DetailNormalMap:
m_Texture: {fileID: 0}
m_Scale: {x: 1, y: 1}
m_Offset: {x: 0, y: 0}
- _EmissionMap:
m_Texture: {fileID: 0}
m_Scale: {x: 1, y: 1}
m_Offset: {x: 0, y: 0}
- _MainTex:
m_Texture: {fileID: 10300, guid: 0000000000000000f000000000000000, type: 0}
m_Scale: {x: 1, y: 1}
m_Offset: {x: 0, y: 0}
- _MetallicGlossMap:
m_Texture: {fileID: 0}
m_Scale: {x: 1, y: 1}
m_Offset: {x: 0, y: 0}
- _OcclusionMap:
m_Texture: {fileID: 0}
m_Scale: {x: 1, y: 1}
m_Offset: {x: 0, y: 0}
- _ParallaxMap:
m_Texture: {fileID: 0}
m_Scale: {x: 1, y: 1}
m_Offset: {x: 0, y: 0}
m_Floats:
- _BumpScale: 1
- _Cutoff: 0.5
- _DetailNormalMapScale: 1
- _DstBlend: 0
- _GlossMapScale: 1
- _Glossiness: 0.5
- _GlossyReflections: 1
- _InvFade: 1
- _Metallic: 0
- _Mode: 0
- _OcclusionStrength: 1
- _Parallax: 0.02
- _SmoothnessTextureChannel: 0
- _SpecularHighlights: 1
- _SrcBlend: 1
- _UVSec: 0
- _ZWrite: 1
m_Colors:
- _Color: {r: 1, g: 1, b: 1, a: 1}
- _EmissionColor: {r: 0, g: 0, b: 0, a: 1}
- _TintColor: {r: 1, g: 1, b: 1, a: 1}

View File

@@ -0,0 +1,9 @@
fileFormatVersion: 2
guid: 35e2e3a06b6570a4cac191d4ca904974
timeCreated: 1508486714
licenseType: Store
NativeFormatImporter:
mainObjectFileID: 2100000
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,78 @@
%YAML 1.1
%TAG !u! tag:unity3d.com,2011:
--- !u!21 &2100000
Material:
serializedVersion: 6
m_ObjectHideFlags: 0
m_PrefabParentObject: {fileID: 0}
m_PrefabInternal: {fileID: 0}
m_Name: Plexus Triangles
m_Shader: {fileID: 200, guid: 0000000000000000f000000000000000, type: 0}
m_ShaderKeywords: _ALPHABLEND_ON _EMISSION
m_LightmapFlags: 1
m_EnableInstancingVariants: 0
m_DoubleSidedGI: 0
m_CustomRenderQueue: -1
stringTagMap: {}
disabledShaderPasses: []
m_SavedProperties:
serializedVersion: 3
m_TexEnvs:
- _BumpMap:
m_Texture: {fileID: 0}
m_Scale: {x: 1, y: 1}
m_Offset: {x: 0, y: 0}
- _DetailAlbedoMap:
m_Texture: {fileID: 0}
m_Scale: {x: 1, y: 1}
m_Offset: {x: 0, y: 0}
- _DetailMask:
m_Texture: {fileID: 0}
m_Scale: {x: 1, y: 1}
m_Offset: {x: 0, y: 0}
- _DetailNormalMap:
m_Texture: {fileID: 0}
m_Scale: {x: 1, y: 1}
m_Offset: {x: 0, y: 0}
- _EmissionMap:
m_Texture: {fileID: 0}
m_Scale: {x: 1, y: 1}
m_Offset: {x: 0, y: 0}
- _MainTex:
m_Texture: {fileID: 0}
m_Scale: {x: 1, y: 1}
m_Offset: {x: 0, y: 0}
- _MetallicGlossMap:
m_Texture: {fileID: 0}
m_Scale: {x: 1, y: 1}
m_Offset: {x: 0, y: 0}
- _OcclusionMap:
m_Texture: {fileID: 0}
m_Scale: {x: 1, y: 1}
m_Offset: {x: 0, y: 0}
- _ParallaxMap:
m_Texture: {fileID: 0}
m_Scale: {x: 1, y: 1}
m_Offset: {x: 0, y: 0}
m_Floats:
- _BumpScale: 1
- _Cutoff: 0.5
- _DetailNormalMapScale: 1
- _DstBlend: 10
- _GlossMapScale: 1
- _Glossiness: 0.5
- _GlossyReflections: 1
- _InvFade: 1
- _Metallic: 0
- _Mode: 2
- _OcclusionStrength: 1
- _Parallax: 0.02
- _SmoothnessTextureChannel: 0
- _SpecularHighlights: 1
- _SrcBlend: 5
- _UVSec: 0
- _ZWrite: 0
m_Colors:
- _Color: {r: 1, g: 1, b: 1, a: 0.2784314}
- _EmissionColor: {r: 0, g: 0, b: 0, a: 1}
- _TintColor: {r: 1, g: 1, b: 1, a: 0.4}

View File

@@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 5d918114c252ee445b2d579c481b0f91
NativeFormatImporter:
externalObjects: {}
mainObjectFileID: 2100000
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,78 @@
%YAML 1.1
%TAG !u! tag:unity3d.com,2011:
--- !u!21 &2100000
Material:
serializedVersion: 6
m_ObjectHideFlags: 0
m_PrefabParentObject: {fileID: 0}
m_PrefabInternal: {fileID: 0}
m_Name: Solid White Circle (Additive)
m_Shader: {fileID: 200, guid: 0000000000000000f000000000000000, type: 0}
m_ShaderKeywords:
m_LightmapFlags: 4
m_EnableInstancingVariants: 0
m_DoubleSidedGI: 0
m_CustomRenderQueue: -1
stringTagMap: {}
disabledShaderPasses: []
m_SavedProperties:
serializedVersion: 3
m_TexEnvs:
- _BumpMap:
m_Texture: {fileID: 0}
m_Scale: {x: 1, y: 1}
m_Offset: {x: 0, y: 0}
- _DetailAlbedoMap:
m_Texture: {fileID: 0}
m_Scale: {x: 1, y: 1}
m_Offset: {x: 0, y: 0}
- _DetailMask:
m_Texture: {fileID: 0}
m_Scale: {x: 1, y: 1}
m_Offset: {x: 0, y: 0}
- _DetailNormalMap:
m_Texture: {fileID: 0}
m_Scale: {x: 1, y: 1}
m_Offset: {x: 0, y: 0}
- _EmissionMap:
m_Texture: {fileID: 0}
m_Scale: {x: 1, y: 1}
m_Offset: {x: 0, y: 0}
- _MainTex:
m_Texture: {fileID: 2800000, guid: 1a0cb63a3bc8d2342852089bfb884192, type: 3}
m_Scale: {x: 1, y: 1}
m_Offset: {x: 0, y: 0}
- _MetallicGlossMap:
m_Texture: {fileID: 0}
m_Scale: {x: 1, y: 1}
m_Offset: {x: 0, y: 0}
- _OcclusionMap:
m_Texture: {fileID: 0}
m_Scale: {x: 1, y: 1}
m_Offset: {x: 0, y: 0}
- _ParallaxMap:
m_Texture: {fileID: 0}
m_Scale: {x: 1, y: 1}
m_Offset: {x: 0, y: 0}
m_Floats:
- _BumpScale: 1
- _Cutoff: 0.5
- _DetailNormalMapScale: 1
- _DstBlend: 0
- _GlossMapScale: 1
- _Glossiness: 0.5
- _GlossyReflections: 1
- _InvFade: 1
- _Metallic: 0
- _Mode: 0
- _OcclusionStrength: 1
- _Parallax: 0.02
- _SmoothnessTextureChannel: 0
- _SpecularHighlights: 1
- _SrcBlend: 1
- _UVSec: 0
- _ZWrite: 1
m_Colors:
- _Color: {r: 1, g: 1, b: 1, a: 1}
- _EmissionColor: {r: 0, g: 0, b: 0, a: 1}
- _TintColor: {r: 1, g: 1, b: 1, a: 1}

View File

@@ -0,0 +1,9 @@
fileFormatVersion: 2
guid: 3f5721af2cf8d7e4b810f19ac7c6f606
timeCreated: 1508486714
licenseType: Store
NativeFormatImporter:
mainObjectFileID: 2100000
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,78 @@
%YAML 1.1
%TAG !u! tag:unity3d.com,2011:
--- !u!21 &2100000
Material:
serializedVersion: 6
m_ObjectHideFlags: 0
m_PrefabParentObject: {fileID: 0}
m_PrefabInternal: {fileID: 0}
m_Name: Solid White Square (Alpha Blended)
m_Shader: {fileID: 200, guid: 0000000000000000f000000000000000, type: 0}
m_ShaderKeywords:
m_LightmapFlags: 4
m_EnableInstancingVariants: 0
m_DoubleSidedGI: 0
m_CustomRenderQueue: -1
stringTagMap: {}
disabledShaderPasses: []
m_SavedProperties:
serializedVersion: 3
m_TexEnvs:
- _BumpMap:
m_Texture: {fileID: 0}
m_Scale: {x: 1, y: 1}
m_Offset: {x: 0, y: 0}
- _DetailAlbedoMap:
m_Texture: {fileID: 0}
m_Scale: {x: 1, y: 1}
m_Offset: {x: 0, y: 0}
- _DetailMask:
m_Texture: {fileID: 0}
m_Scale: {x: 1, y: 1}
m_Offset: {x: 0, y: 0}
- _DetailNormalMap:
m_Texture: {fileID: 0}
m_Scale: {x: 1, y: 1}
m_Offset: {x: 0, y: 0}
- _EmissionMap:
m_Texture: {fileID: 0}
m_Scale: {x: 1, y: 1}
m_Offset: {x: 0, y: 0}
- _MainTex:
m_Texture: {fileID: 2800000, guid: fcc934170231d0244809002a4923c98b, type: 3}
m_Scale: {x: 1, y: 1}
m_Offset: {x: 0, y: 0}
- _MetallicGlossMap:
m_Texture: {fileID: 0}
m_Scale: {x: 1, y: 1}
m_Offset: {x: 0, y: 0}
- _OcclusionMap:
m_Texture: {fileID: 0}
m_Scale: {x: 1, y: 1}
m_Offset: {x: 0, y: 0}
- _ParallaxMap:
m_Texture: {fileID: 0}
m_Scale: {x: 1, y: 1}
m_Offset: {x: 0, y: 0}
m_Floats:
- _BumpScale: 1
- _Cutoff: 0.5
- _DetailNormalMapScale: 1
- _DstBlend: 0
- _GlossMapScale: 1
- _Glossiness: 0.5
- _GlossyReflections: 1
- _InvFade: 1
- _Metallic: 0
- _Mode: 0
- _OcclusionStrength: 1
- _Parallax: 0.02
- _SmoothnessTextureChannel: 0
- _SpecularHighlights: 1
- _SrcBlend: 1
- _UVSec: 0
- _ZWrite: 1
m_Colors:
- _Color: {r: 1, g: 1, b: 1, a: 1}
- _EmissionColor: {r: 0, g: 0, b: 0, a: 1}
- _TintColor: {r: 1, g: 1, b: 1, a: 1}

View File

@@ -0,0 +1,9 @@
fileFormatVersion: 2
guid: 01cfa300c642b654b93f44f9c3a0006f
timeCreated: 1508486714
licenseType: Store
NativeFormatImporter:
mainObjectFileID: 2100000
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,9 @@
fileFormatVersion: 2
guid: f17469a07497ddd47a2328c68fde2d77
folderAsset: yes
timeCreated: 1508401765
licenseType: Store
DefaultImporter:
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,320 @@
%YAML 1.1
%TAG !u! tag:unity3d.com,2011:
--- !u!114 &11400000
MonoBehaviour:
m_ObjectHideFlags: 0
m_PrefabParentObject: {fileID: 0}
m_PrefabInternal: {fileID: 0}
m_GameObject: {fileID: 0}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: 8a3bdb2cd68f901469e7cc149151eb49, type: 3}
m_Name: Particle Plexus Post-Processing Profile
m_EditorClassIdentifier:
debugViews:
m_Enabled: 1
m_Settings:
mode: 0
depth:
scale: 1
motionVectors:
sourceOpacity: 1
motionImageOpacity: 0
motionImageAmplitude: 16
motionVectorsOpacity: 1
motionVectorsResolution: 24
motionVectorsAmplitude: 64
fog:
m_Enabled: 0
m_Settings:
excludeSkybox: 1
antialiasing:
m_Enabled: 0
m_Settings:
method: 0
fxaaSettings:
preset: 2
taaSettings:
jitterSpread: 0.75
sharpen: 0.3
stationaryBlending: 0.95
motionBlending: 0.85
ambientOcclusion:
m_Enabled: 0
m_Settings:
intensity: 1
radius: 0.3
sampleCount: 10
downsampling: 1
forceForwardCompatibility: 0
ambientOnly: 0
highPrecision: 0
screenSpaceReflection:
m_Enabled: 0
m_Settings:
reflection:
blendType: 0
reflectionQuality: 2
maxDistance: 100
iterationCount: 256
stepSize: 3
widthModifier: 0.5
reflectionBlur: 1
reflectBackfaces: 0
intensity:
reflectionMultiplier: 1
fadeDistance: 100
fresnelFade: 1
fresnelFadePower: 1
screenEdgeMask:
intensity: 0.03
depthOfField:
m_Enabled: 0
m_Settings:
focusDistance: 5
aperture: 5.6
focalLength: 50
useCameraFov: 0
kernelSize: 1
motionBlur:
m_Enabled: 0
m_Settings:
shutterAngle: 270
sampleCount: 10
frameBlending: 0
eyeAdaptation:
m_Enabled: 0
m_Settings:
lowPercent: 45
highPercent: 95
minLuminance: -5
maxLuminance: 1
keyValue: 0.25
dynamicKeyValue: 1
adaptationType: 0
speedUp: 2
speedDown: 1
logMin: -8
logMax: 4
bloom:
m_Enabled: 1
m_Settings:
bloom:
intensity: 1.5
threshold: 0.8
softKnee: 0
radius: 7
antiFlicker: 0
lensDirt:
texture: {fileID: 0}
intensity: 3
colorGrading:
m_Enabled: 1
m_Settings:
tonemapping:
tonemapper: 1
neutralBlackIn: 0.02
neutralWhiteIn: 10
neutralBlackOut: 0
neutralWhiteOut: 10
neutralWhiteLevel: 5.3
neutralWhiteClip: 10
basic:
postExposure: 1
temperature: 0
tint: 0
hueShift: 0
saturation: 0.9
contrast: 1.15
channelMixer:
red: {x: 1, y: 0, z: 0}
green: {x: 0, y: 1, z: 0}
blue: {x: 0, y: 0, z: 1}
currentEditingChannel: 0
colorWheels:
mode: 1
log:
slope: {r: 1, g: 1, b: 1, a: 0}
power: {r: 1, g: 1, b: 1, a: 0}
offset: {r: 1, g: 1, b: 1, a: 0}
linear:
lift: {r: 0, g: 0, b: 0, a: 0}
gamma: {r: 0, g: 0, b: 0, a: 0}
gain: {r: 0, g: 0, b: 0, a: 0}
curves:
master:
curve:
serializedVersion: 2
m_Curve:
- serializedVersion: 2
time: 0
value: 0
inSlope: 1
outSlope: 1
tangentMode: 0
- serializedVersion: 2
time: 1
value: 1
inSlope: 1
outSlope: 1
tangentMode: 0
m_PreInfinity: 2
m_PostInfinity: 2
m_RotationOrder: 0
m_Loop: 0
m_ZeroValue: 0
m_Range: 1
red:
curve:
serializedVersion: 2
m_Curve:
- serializedVersion: 2
time: 0
value: 0
inSlope: 1
outSlope: 1
tangentMode: 0
- serializedVersion: 2
time: 1
value: 1
inSlope: 1
outSlope: 1
tangentMode: 0
m_PreInfinity: 2
m_PostInfinity: 2
m_RotationOrder: 4
m_Loop: 0
m_ZeroValue: 0
m_Range: 1
green:
curve:
serializedVersion: 2
m_Curve:
- serializedVersion: 2
time: 0
value: 0
inSlope: 1
outSlope: 1
tangentMode: 0
- serializedVersion: 2
time: 1
value: 1
inSlope: 1
outSlope: 1
tangentMode: 0
m_PreInfinity: 2
m_PostInfinity: 2
m_RotationOrder: 4
m_Loop: 0
m_ZeroValue: 0
m_Range: 1
blue:
curve:
serializedVersion: 2
m_Curve:
- serializedVersion: 2
time: 0
value: 0
inSlope: 1
outSlope: 1
tangentMode: 0
- serializedVersion: 2
time: 1
value: 1
inSlope: 1
outSlope: 1
tangentMode: 0
m_PreInfinity: 2
m_PostInfinity: 2
m_RotationOrder: 4
m_Loop: 0
m_ZeroValue: 0
m_Range: 1
hueVShue:
curve:
serializedVersion: 2
m_Curve: []
m_PreInfinity: 2
m_PostInfinity: 2
m_RotationOrder: 4
m_Loop: 1
m_ZeroValue: 0.5
m_Range: 1
hueVSsat:
curve:
serializedVersion: 2
m_Curve: []
m_PreInfinity: 2
m_PostInfinity: 2
m_RotationOrder: 4
m_Loop: 1
m_ZeroValue: 0.5
m_Range: 1
satVSsat:
curve:
serializedVersion: 2
m_Curve: []
m_PreInfinity: 2
m_PostInfinity: 2
m_RotationOrder: 4
m_Loop: 0
m_ZeroValue: 0.5
m_Range: 1
lumVSsat:
curve:
serializedVersion: 2
m_Curve: []
m_PreInfinity: 2
m_PostInfinity: 2
m_RotationOrder: 4
m_Loop: 0
m_ZeroValue: 0.5
m_Range: 1
e_CurrentEditingCurve: 0
e_CurveY: 1
e_CurveR: 0
e_CurveG: 0
e_CurveB: 0
userLut:
m_Enabled: 0
m_Settings:
lut: {fileID: 0}
contribution: 1
chromaticAberration:
m_Enabled: 1
m_Settings:
spectralTexture: {fileID: 0}
intensity: 1
grain:
m_Enabled: 1
m_Settings:
colored: 1
intensity: 0.25
size: 0.5
luminanceContribution: 0.8
vignette:
m_Enabled: 1
m_Settings:
mode: 0
color: {r: 0, g: 0, b: 0, a: 1}
center: {x: 0.5, y: 0.5}
intensity: 0.45
smoothness: 0.2
roundness: 1
mask: {fileID: 0}
opacity: 1
rounded: 0
dithering:
m_Enabled: 0
monitors:
currentMonitorID: 0
refreshOnPlay: 0
histogramMode: 3
waveformExposure: 0.12
waveformY: 0
waveformR: 1
waveformG: 1
waveformB: 1
paradeExposure: 0.12
vectorscopeExposure: 0.12
vectorscopeShowBackground: 1

View File

@@ -0,0 +1,9 @@
fileFormatVersion: 2
guid: 8db3f21d0d527d74daec47111a2c2731
timeCreated: 1508401783
licenseType: Store
NativeFormatImporter:
mainObjectFileID: 11400000
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,9 @@
fileFormatVersion: 2
guid: 69a3065ca67adce4c969963284e8f467
folderAsset: yes
timeCreated: 1508486547
licenseType: Store
DefaultImporter:
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,134 @@
%YAML 1.1
%TAG !u! tag:unity3d.com,2011:
--- !u!1001 &100100000
Prefab:
m_ObjectHideFlags: 1
serializedVersion: 2
m_Modification:
m_TransformParent: {fileID: 0}
m_Modifications: []
m_RemovedComponents: []
m_ParentPrefab: {fileID: 0}
m_RootGameObject: {fileID: 1386574972781608}
m_IsPrefabParent: 1
--- !u!1 &1386574972781608
GameObject:
m_ObjectHideFlags: 0
m_PrefabParentObject: {fileID: 0}
m_PrefabInternal: {fileID: 100100000}
serializedVersion: 5
m_Component:
- component: {fileID: 4165100386123906}
- component: {fileID: 120042951271217888}
m_Layer: 0
m_Name: Particle Plexus Line Renderer Template 2
m_TagString: Untagged
m_Icon: {fileID: 0}
m_NavMeshLayer: 0
m_StaticEditorFlags: 0
m_IsActive: 1
--- !u!4 &4165100386123906
Transform:
m_ObjectHideFlags: 1
m_PrefabParentObject: {fileID: 0}
m_PrefabInternal: {fileID: 100100000}
m_GameObject: {fileID: 1386574972781608}
m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
m_LocalPosition: {x: 0, y: 0, z: 0}
m_LocalScale: {x: 1, y: 1, z: 1}
m_Children: []
m_Father: {fileID: 0}
m_RootOrder: 0
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
--- !u!120 &120042951271217888
LineRenderer:
m_ObjectHideFlags: 1
m_PrefabParentObject: {fileID: 0}
m_PrefabInternal: {fileID: 100100000}
m_GameObject: {fileID: 1386574972781608}
m_Enabled: 1
m_CastShadows: 1
m_ReceiveShadows: 1
m_DynamicOccludee: 1
m_MotionVectors: 0
m_LightProbeUsage: 0
m_ReflectionProbeUsage: 0
m_RenderingLayerMask: 4294967295
m_Materials:
- {fileID: 2100000, guid: 01cfa300c642b654b93f44f9c3a0006f, type: 2}
m_StaticBatchInfo:
firstSubMesh: 0
subMeshCount: 0
m_StaticBatchRoot: {fileID: 0}
m_ProbeAnchor: {fileID: 0}
m_LightProbeVolumeOverride: {fileID: 0}
m_ScaleInLightmap: 1
m_PreserveUVs: 0
m_IgnoreNormalsForChartDetection: 0
m_ImportantGI: 0
m_StitchLightmapSeams: 0
m_SelectedEditorRenderState: 3
m_MinimumChartSize: 4
m_AutoUVMaxDistance: 0.5
m_AutoUVMaxAngle: 89
m_LightmapParameters: {fileID: 0}
m_SortingLayerID: 0
m_SortingLayer: 0
m_SortingOrder: 0
m_Positions:
- {x: 0, y: 0, z: 0}
- {x: 0, y: 0, z: 1}
m_Parameters:
serializedVersion: 2
widthMultiplier: 0.1
widthCurve:
serializedVersion: 2
m_Curve:
- serializedVersion: 3
time: 0
value: 1
inSlope: 0
outSlope: 0
tangentMode: 0
weightedMode: 0
inWeight: 0.33333334
outWeight: 0.33333334
m_PreInfinity: 2
m_PostInfinity: 2
m_RotationOrder: 4
colorGradient:
serializedVersion: 2
key0: {r: 1, g: 1, b: 1, a: 1}
key1: {r: 1, g: 1, b: 1, a: 1}
key2: {r: 0, g: 0, b: 0, a: 0}
key3: {r: 0, g: 0, b: 0, a: 0}
key4: {r: 0, g: 0, b: 0, a: 0}
key5: {r: 0, g: 0, b: 0, a: 0}
key6: {r: 0, g: 0, b: 0, a: 0}
key7: {r: 0, g: 0, b: 0, a: 0}
ctime0: 0
ctime1: 65535
ctime2: 0
ctime3: 0
ctime4: 0
ctime5: 0
ctime6: 0
ctime7: 0
atime0: 0
atime1: 65535
atime2: 0
atime3: 0
atime4: 0
atime5: 0
atime6: 0
atime7: 0
m_Mode: 0
m_NumColorKeys: 2
m_NumAlphaKeys: 2
numCornerVertices: 0
numCapVertices: 0
alignment: 0
textureMode: 0
generateLightingData: 0
m_UseWorldSpace: 1
m_Loop: 0

View File

@@ -0,0 +1,9 @@
fileFormatVersion: 2
guid: 811a192407d7b8f449de20b725a2938a
timeCreated: 1508486655
licenseType: Store
NativeFormatImporter:
mainObjectFileID: 100100000
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,130 @@
%YAML 1.1
%TAG !u! tag:unity3d.com,2011:
--- !u!1001 &100100000
Prefab:
m_ObjectHideFlags: 1
serializedVersion: 2
m_Modification:
m_TransformParent: {fileID: 0}
m_Modifications: []
m_RemovedComponents: []
m_ParentPrefab: {fileID: 0}
m_RootGameObject: {fileID: 1386574972781608}
m_IsPrefabParent: 1
--- !u!1 &1386574972781608
GameObject:
m_ObjectHideFlags: 0
m_PrefabParentObject: {fileID: 0}
m_PrefabInternal: {fileID: 100100000}
serializedVersion: 5
m_Component:
- component: {fileID: 4165100386123906}
- component: {fileID: 120042951271217888}
m_Layer: 0
m_Name: Particle Plexus Line Renderer Template
m_TagString: Untagged
m_Icon: {fileID: 0}
m_NavMeshLayer: 0
m_StaticEditorFlags: 0
m_IsActive: 1
--- !u!4 &4165100386123906
Transform:
m_ObjectHideFlags: 1
m_PrefabParentObject: {fileID: 0}
m_PrefabInternal: {fileID: 100100000}
m_GameObject: {fileID: 1386574972781608}
m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
m_LocalPosition: {x: 0, y: 0, z: 0}
m_LocalScale: {x: 1, y: 1, z: 1}
m_Children: []
m_Father: {fileID: 0}
m_RootOrder: 0
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
--- !u!120 &120042951271217888
LineRenderer:
m_ObjectHideFlags: 1
m_PrefabParentObject: {fileID: 0}
m_PrefabInternal: {fileID: 100100000}
m_GameObject: {fileID: 1386574972781608}
m_Enabled: 1
m_CastShadows: 1
m_ReceiveShadows: 1
m_DynamicOccludee: 1
m_MotionVectors: 0
m_LightProbeUsage: 0
m_ReflectionProbeUsage: 0
m_Materials:
- {fileID: 2100000, guid: 35e2e3a06b6570a4cac191d4ca904974, type: 2}
m_StaticBatchInfo:
firstSubMesh: 0
subMeshCount: 0
m_StaticBatchRoot: {fileID: 0}
m_ProbeAnchor: {fileID: 0}
m_LightProbeVolumeOverride: {fileID: 0}
m_ScaleInLightmap: 1
m_PreserveUVs: 0
m_IgnoreNormalsForChartDetection: 0
m_ImportantGI: 0
m_StitchLightmapSeams: 0
m_SelectedEditorRenderState: 3
m_MinimumChartSize: 4
m_AutoUVMaxDistance: 0.5
m_AutoUVMaxAngle: 89
m_LightmapParameters: {fileID: 0}
m_SortingLayerID: 0
m_SortingLayer: 0
m_SortingOrder: 0
m_Positions:
- {x: 0, y: 0, z: 0}
- {x: 0, y: 0, z: 1}
m_Parameters:
serializedVersion: 2
widthMultiplier: 0.1
widthCurve:
serializedVersion: 2
m_Curve:
- serializedVersion: 2
time: 0
value: 1
inSlope: 0
outSlope: 0
tangentMode: 0
m_PreInfinity: 2
m_PostInfinity: 2
m_RotationOrder: 4
colorGradient:
serializedVersion: 2
key0: {r: 1, g: 1, b: 1, a: 1}
key1: {r: 1, g: 1, b: 1, a: 1}
key2: {r: 0, g: 0, b: 0, a: 0}
key3: {r: 0, g: 0, b: 0, a: 0}
key4: {r: 0, g: 0, b: 0, a: 0}
key5: {r: 0, g: 0, b: 0, a: 0}
key6: {r: 0, g: 0, b: 0, a: 0}
key7: {r: 0, g: 0, b: 0, a: 0}
ctime0: 0
ctime1: 65535
ctime2: 0
ctime3: 0
ctime4: 0
ctime5: 0
ctime6: 0
ctime7: 0
atime0: 0
atime1: 65535
atime2: 0
atime3: 0
atime4: 0
atime5: 0
atime6: 0
atime7: 0
m_Mode: 0
m_NumColorKeys: 2
m_NumAlphaKeys: 2
numCornerVertices: 0
numCapVertices: 0
alignment: 0
textureMode: 0
generateLightingData: 0
m_UseWorldSpace: 1
m_Loop: 0

View File

@@ -0,0 +1,9 @@
fileFormatVersion: 2
guid: 8f3c2176600c9f849accec9070807b4c
timeCreated: 1508486655
licenseType: Store
NativeFormatImporter:
mainObjectFileID: 100100000
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,9 @@
fileFormatVersion: 2
guid: f41fb4812cb5fe947b4a34ca6417fb4d
folderAsset: yes
timeCreated: 1508486470
licenseType: Store
DefaultImporter:
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 5d714a506331b704ab6494f60e605ef7
timeCreated: 1508486513
licenseType: Store
DefaultImporter:
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 9d6f4d9c6527fdf448ccbece1878b71f
timeCreated: 1508486513
licenseType: Store
DefaultImporter:
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,9 @@
fileFormatVersion: 2
guid: 95f78947de6b3fe458563de77b4b20a3
folderAsset: yes
timeCreated: 1508398165
licenseType: Store
DefaultImporter:
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,50 @@
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class ParticlePlexusDemo_CameraRig : MonoBehaviour
{
public Transform pivot;
Vector3 targetRotation;
[Range(0.0f, 90.0f)]
public float rotationLimit = 90.0f;
public float rotationSpeed = 2.0f;
public float rotationLerpSpeed = 4.0f;
Vector3 startRotation;
void Start()
{
startRotation = pivot.localEulerAngles;
targetRotation = startRotation;
}
void Update()
{
float horizontal = Input.GetAxis("Horizontal");
float vertical = Input.GetAxis("Vertical");
if (Input.GetKeyDown(KeyCode.R))
{
targetRotation = startRotation;
}
horizontal *= rotationSpeed;
vertical *= rotationSpeed;
targetRotation.y += horizontal;
targetRotation.x += vertical;
targetRotation.x = Mathf.Clamp(targetRotation.x, -rotationLimit, rotationLimit);
targetRotation.y = Mathf.Clamp(targetRotation.y, -rotationLimit, rotationLimit);
Vector3 currentRotation = pivot.localEulerAngles;
currentRotation.x = Mathf.LerpAngle(currentRotation.x, targetRotation.x, Time.deltaTime * rotationLerpSpeed);
currentRotation.y = Mathf.LerpAngle(currentRotation.y, targetRotation.y, Time.deltaTime * rotationLerpSpeed);
pivot.localEulerAngles = currentRotation;
}
}

View File

@@ -0,0 +1,12 @@
fileFormatVersion: 2
guid: c45c745708239bb4faf150bbfcddd20b
timeCreated: 1508405059
licenseType: Store
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,9 @@
fileFormatVersion: 2
guid: 11e544dc2c8eb384ba0a1b186b7a4cbf
folderAsset: yes
timeCreated: 1485465673
licenseType: Store
DefaultImporter:
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,841 @@
// =================================
// Namespaces.
// =================================
using UnityEngine;
using System.Collections.Generic;
using System.Threading;
// =================================
// Define namespace.
// =================================
namespace MirzaBeig
{
namespace Scripting
{
namespace Effects
{
// =================================
// Classes.
// =================================
[RequireComponent(typeof(ParticleSystem))]
[AddComponentMenu("Effects/Particle Plexus")]
public class ParticlePlexus : MonoBehaviour
{
// =================================
// Nested classes and structures.
// =================================
// ...
// =================================
// Variables.
// =================================
// ...
public float maxDistance = 1.0f;
public int maxConnections = 5;
public int maxLineRenderers = 100;
[Space]
[Range(0.0f, 1.0f)]
public float widthFromParticle = 0.125f;
[Space]
[Range(0.0f, 1.0f)]
public float colourFromParticle = 1.0f;
[Range(0.0f, 1.0f)]
public float alphaFromParticle = 1.0f;
[Space]
public AnimationCurve alphaOverNormalizedDistance = AnimationCurve.Linear(0.0f, 1.0f, 1.0f, 1.0f);
//public float fadeInTime = 0.0f;
new ParticleSystem particleSystem;
ParticleSystem.Particle[] particles;
Vector3[] particlePositions;
Color[] particleColours;
float[] particleSizes;
ParticleSystem.MainModule particleSystemMainModule;
[Space]
public LineRenderer lineRendererTemplate;
List<LineRenderer> lineRenderers = new List<LineRenderer>();
//[System.Serializable]
//public struct LineRendererData
//{
// public float currentStartParticleID;
// public float currentEndParticleID;
// public float previousStartParticleID;
// public float previousEndParticleID;
// public float timer;
//}
//List<LineRendererData> lineRendererData = new List<LineRendererData>();
Transform _transform;
[Header("Triangle Mesh Settings")]
public MeshFilter trianglesMeshFilter;
Mesh trianglesMesh;
List<int[]> allConnectedParticles = new List<int[]>();
[Space]
// Triangles can be limited to those with particles who
// are a fraction of the distance limit from other particles.
// Example:
// 1.0 == use same distance as maxDistance.
// 0.5 == half of maxDistance.
[Range(0.0f, 1.0f)]
public float maxDistanceTriangleBias = 1.0f;
[Space]
// Additional filtering for triangle generation so that it's more based on distance to adjacent particles.
public bool trianglesDistanceCheck = false;
[Space]
[Range(0.0f, 1.0f)]
public float triangleColourFromParticle = 1.0f;
[Range(0.0f, 1.0f)]
public float triangleAlphaFromParticle = 1.0f;
[Header("General Performance Settings")]
[Range(0.0f, 1.0f)]
public float delay = 0.0f;
float timer;
public bool alwaysUpdate = false;
bool visible;
//List<Vector4> customParticleData = new List<Vector4>();
//int uniqueParticleID;
// =================================
// Functions.
// =================================
// ...
void Start()
{
particleSystem = GetComponent<ParticleSystem>();
particleSystemMainModule = particleSystem.main;
_transform = transform;
if (trianglesMeshFilter)
{
trianglesMesh = new Mesh();
trianglesMeshFilter.mesh = trianglesMesh;
// Unparent since I don't want it following me, but I may have
// parented in the scene for organization.
// EDIT: Nevermind, let the user deal with this as they see fit.
//if (trianglesMeshFilter.transform != transform)
//{
// trianglesMeshFilter.transform.parent = null;
//}
}
}
// ...
void OnDisable()
{
for (int i = 0; i < lineRenderers.Count; i++)
{
lineRenderers[i].enabled = false;
}
}
// ...
void OnBecameVisible()
{
visible = true;
}
void OnBecameInvisible()
{
visible = false;
}
// ...
void LateUpdate()
{
if (trianglesMeshFilter)
{
switch (particleSystemMainModule.simulationSpace)
{
case ParticleSystemSimulationSpace.World:
{
// Make sure this is always at origin, or triangle mesh moves out of sync since
// the mesh triangle vertices are already set to the world space particle positions.
trianglesMeshFilter.transform.position = Vector3.zero;
break;
}
case ParticleSystemSimulationSpace.Local:
{
// In local space it should follow me.
trianglesMeshFilter.transform.position = transform.position;
trianglesMeshFilter.transform.rotation = transform.rotation;
break;
}
case ParticleSystemSimulationSpace.Custom:
{
// In custom space it should follow the custom transform.
trianglesMeshFilter.transform.position = particleSystemMainModule.customSimulationSpace.position;
trianglesMeshFilter.transform.rotation = particleSystemMainModule.customSimulationSpace.rotation;
break;
}
}
}
// Filter doesn't exist but mesh is there? That means the filter reference was lost. Clear the mesh.
// AKA... If mesh filter is gone (deleted and/or reference nulled), clear the mesh.
else if (trianglesMesh)
{
trianglesMesh.Clear();
}
int lineRenderersCount = lineRenderers.Count;
// In case max line renderers value is changed at runtime -> destroy extra.
if (lineRenderersCount > maxLineRenderers)
{
for (int i = maxLineRenderers; i < lineRenderersCount; i++)
{
Destroy(lineRenderers[i].gameObject);
}
lineRenderers.RemoveRange(maxLineRenderers, lineRenderersCount - maxLineRenderers);
//lineRendererData.RemoveRange(maxLineRenderers, lineRenderersCount - maxLineRenderers);
lineRenderersCount -= lineRenderersCount - maxLineRenderers;
}
if (alwaysUpdate || visible)
{
// Prevent constant allocations so long as max particle count doesn't change.
int maxParticles = particleSystemMainModule.maxParticles;
if (particles == null || particles.Length < maxParticles)
{
particles = new ParticleSystem.Particle[maxParticles];
particlePositions = new Vector3[maxParticles];
particleColours = new Color[maxParticles];
particleSizes = new float[maxParticles];
}
float deltaTime = Time.deltaTime;
timer += deltaTime;
if (timer >= delay)
{
timer = 0.0f;
int lrIndex = 0;
allConnectedParticles.Clear();
// Only update if drawing/making connections.
if (maxConnections > 0 && maxLineRenderers > 0)
{
particleSystem.GetParticles(particles);
//particleSystem.GetCustomParticleData(customParticleData, ParticleSystemCustomData.Custom1);
int particleCount = particleSystem.particleCount;
float maxDistanceSqr = maxDistance * maxDistance;
ParticleSystemSimulationSpace simulationSpace = particleSystemMainModule.simulationSpace;
ParticleSystemScalingMode scalingMode = particleSystemMainModule.scalingMode;
Transform customSimulationSpaceTransform = particleSystemMainModule.customSimulationSpace;
Color lineRendererStartColour = lineRendererTemplate.startColor;
Color lineRendererEndColour = lineRendererTemplate.endColor;
float lineRendererStartWidth = lineRendererTemplate.startWidth * lineRendererTemplate.widthMultiplier;
float lineRendererEndWidth = lineRendererTemplate.endWidth * lineRendererTemplate.widthMultiplier;
// Save particle properties in a quick loop (accessing these is expensive and loops significantly more later, so it's better to save them once now).
for (int i = 0; i < particleCount; i++)
{
particlePositions[i] = particles[i].position;
particleColours[i] = particles[i].GetCurrentColor(particleSystem);
particleSizes[i] = particles[i].GetCurrentSize(particleSystem);
// Default is 0.0f, so if default, this is a new particle and I need to assign a custom ID.
//if (customParticleData[i].x == 0.0f)
//{
// // ++value -> increment first, then return that value.
// // That way it won't be zero (default) the first time I use it.
// customParticleData[i] = new Vector4(++uniqueParticleID, 0, 0, 0);
//}
}
//particleSystem.SetCustomParticleData(customParticleData, ParticleSystemCustomData.Custom1);
Vector3 p1p2_difference;
// If in world space, there's no need to do any of the extra calculations... simplify the loop!
if (simulationSpace == ParticleSystemSimulationSpace.World)
{
for (int i = 0; i < particleCount; i++)
{
if (lrIndex == maxLineRenderers)
{
break;
}
Color particleColour = particleColours[i];
Color lineStartColour = Color.LerpUnclamped(lineRendererStartColour, particleColour, colourFromParticle);
float lineStartColourOriginalAlpha = Mathf.LerpUnclamped(lineRendererStartColour.a, particleColour.a, alphaFromParticle);
lineStartColour.a = lineStartColourOriginalAlpha;
float lineStartWidth = Mathf.LerpUnclamped(lineRendererStartWidth, particleSizes[i], widthFromParticle);
int connections = 0;
int[] connectedParticles = new int[maxConnections + 1];
for (int j = i + 1; j < particleCount; j++)
{
p1p2_difference.x = particlePositions[i].x - particlePositions[j].x;
p1p2_difference.y = particlePositions[i].y - particlePositions[j].y;
p1p2_difference.z = particlePositions[i].z - particlePositions[j].z;
//float distanceSqr = Vector3.SqrMagnitude(p1p2_difference);
float distanceSqr =
p1p2_difference.x * p1p2_difference.x +
p1p2_difference.y * p1p2_difference.y +
p1p2_difference.z * p1p2_difference.z;
if (distanceSqr <= maxDistanceSqr)
{
LineRenderer lr;
if (lrIndex == lineRenderersCount)
{
lr = Instantiate(lineRendererTemplate, _transform, false);
lineRenderers.Add(lr);
lineRenderersCount++;
}
lr = lineRenderers[lrIndex]; lr.enabled = true;
lr.SetPosition(0, particlePositions[i]);
lr.SetPosition(1, particlePositions[j]);
float alphaAttenuation = alphaOverNormalizedDistance.Evaluate(distanceSqr / maxDistanceSqr);
lineStartColour.a = lineStartColourOriginalAlpha * alphaAttenuation;
lr.startColor = lineStartColour;
particleColour = particleColours[j];
Color lineEndColour = Color.LerpUnclamped(lineRendererEndColour, particleColour, colourFromParticle);
lineEndColour.a = Mathf.LerpUnclamped(lineRendererEndColour.a, particleColour.a, alphaFromParticle);
lr.endColor = lineEndColour;
lr.startWidth = lineStartWidth;
lr.endWidth = Mathf.LerpUnclamped(lineRendererEndWidth, particleSizes[j], widthFromParticle);
lrIndex++;
connections++;
// Intentionally taken AFTER connections++ (because index = 0 is the i'th / line origin particle).
connectedParticles[connections] = j;
if (connections == maxConnections || lrIndex == maxLineRenderers)
{
break;
}
}
}
if (connections >= 2)
{
connectedParticles[0] = i;
allConnectedParticles.Add(connectedParticles);
}
}
}
else
{
Vector3 position = Vector3.zero;
Quaternion rotation = Quaternion.identity;
Vector3 localScale = Vector3.one;
Transform simulationSpaceTransform = _transform;
switch (simulationSpace)
{
case ParticleSystemSimulationSpace.Local:
{
position = simulationSpaceTransform.position;
rotation = simulationSpaceTransform.rotation;
localScale = simulationSpaceTransform.localScale;
break;
}
case ParticleSystemSimulationSpace.Custom:
{
simulationSpaceTransform = customSimulationSpaceTransform;
position = simulationSpaceTransform.position;
rotation = simulationSpaceTransform.rotation;
localScale = simulationSpaceTransform.localScale;
break;
}
default:
{
throw new System.NotSupportedException(
string.Format("Unsupported scaling mode '{0}'.", simulationSpace));
}
}
// I put these here so I can take out the default exception case.
// Else I'd have a compiler error for potentially unassigned variables.
Vector3 p1_position = Vector3.zero;
Vector3 p2_position = Vector3.zero;
for (int i = 0; i < particleCount; i++)
{
if (lrIndex == maxLineRenderers)
{
break;
}
switch (simulationSpace)
{
case ParticleSystemSimulationSpace.Local:
case ParticleSystemSimulationSpace.Custom:
{
switch (scalingMode)
{
case ParticleSystemScalingMode.Hierarchy:
{
p1_position = simulationSpaceTransform.TransformPoint(particlePositions[i]);
break;
}
case ParticleSystemScalingMode.Local:
{
// Order is important.
//p1_position = Vector3.Scale(particlePositions[i], localScale);
p1_position.x = particlePositions[i].x * localScale.x;
p1_position.y = particlePositions[i].y * localScale.y;
p1_position.z = particlePositions[i].z * localScale.z;
p1_position = rotation * p1_position;
//p1_position += position;
p1_position.x += position.x;
p1_position.y += position.y;
p1_position.z += position.z;
break;
}
case ParticleSystemScalingMode.Shape:
{
// Order is important.
p1_position = rotation * particlePositions[i];
//p1_position += position;
p1_position.x += position.x;
p1_position.y += position.y;
p1_position.z += position.z;
break;
}
default:
{
throw new System.NotSupportedException(
string.Format("Unsupported scaling mode '{0}'.", scalingMode));
}
}
break;
}
}
Color particleColour = particleColours[i];
Color lineStartColour = Color.LerpUnclamped(lineRendererStartColour, particleColour, colourFromParticle);
float lineStartColourOriginalAlpha = Mathf.LerpUnclamped(lineRendererStartColour.a, particleColour.a, alphaFromParticle);
lineStartColour.a = lineStartColourOriginalAlpha;
float lineStartWidth = Mathf.LerpUnclamped(lineRendererStartWidth, particleSizes[i], widthFromParticle);
int connections = 0;
int[] connectedParticles = new int[maxConnections + 1];
for (int j = i + 1; j < particleCount; j++)
{
// Note that because particles array is not sorted by distance,
// but rather by spawn time (I think), the connections made are
// not necessarily the closest.
switch (simulationSpace)
{
case ParticleSystemSimulationSpace.Local:
case ParticleSystemSimulationSpace.Custom:
{
switch (scalingMode)
{
case ParticleSystemScalingMode.Hierarchy:
{
p2_position = simulationSpaceTransform.TransformPoint(particlePositions[j]);
break;
}
case ParticleSystemScalingMode.Local:
{
// Order is important.
//p2_position = Vector3.Scale(particlePositions[j], localScale);
p2_position.x = particlePositions[j].x * localScale.x;
p2_position.y = particlePositions[j].y * localScale.y;
p2_position.z = particlePositions[j].z * localScale.z;
p2_position = rotation * p2_position;
//p2_position += position;
p2_position.x += position.x;
p2_position.y += position.y;
p2_position.z += position.z;
break;
}
case ParticleSystemScalingMode.Shape:
{
// Order is important.
p2_position = rotation * particlePositions[j];
//p2_position += position;
p2_position.x += position.x;
p2_position.y += position.y;
p2_position.z += position.z;
break;
}
default:
{
throw new System.NotSupportedException(
string.Format("Unsupported scaling mode '{0}'.", scalingMode));
}
}
break;
}
}
p1p2_difference.x = particlePositions[i].x - particlePositions[j].x;
p1p2_difference.y = particlePositions[i].y - particlePositions[j].y;
p1p2_difference.z = particlePositions[i].z - particlePositions[j].z;
// Note that distance is always calculated in WORLD SPACE.
// Scaling the particle system will stretch the distances
// and may require adjusting the maxDistance value.
// I could also do it in local space (which may actually make more
// sense) by just getting the difference of the positions without
// all the transformations. This also provides opportunity for
// optimization as I can limit the world space transform calculations
// to only happen if a particle is within range.
// Think about: Putting in a bool to switch between the two?
//float distanceSqr = Vector3.SqrMagnitude(p1p2_difference);
float distanceSqr =
p1p2_difference.x * p1p2_difference.x +
p1p2_difference.y * p1p2_difference.y +
p1p2_difference.z * p1p2_difference.z;
// If distance to particle within range, add new vertex position.
// The larger the max distance, the quicker connections will
// reach its max, terminating the loop earlier. So even though more lines have
// to be drawn, it's still faster to have a larger maxDistance value because
// the call to Vector3.Distance() is expensive.
if (distanceSqr <= maxDistanceSqr)
{
LineRenderer lr;
if (lrIndex == lineRenderersCount)
{
lr = Instantiate(lineRendererTemplate, _transform, false);
lineRenderers.Add(lr);
lineRenderersCount++;
//lineRendererData.Add(new LineRendererData());
}
lr = lineRenderers[lrIndex];
//LineRendererData lrd = lineRendererData[lrIndex];
lr.enabled = true;
//lrd.previousStartParticleID = lrd.currentStartParticleID;
//lrd.previousEndParticleID = lrd.currentEndParticleID;
//lrd.currentStartParticleID = customParticleData[i].x;
//lrd.currentEndParticleID = customParticleData[j].x;
lr.SetPosition(0, p1_position);
lr.SetPosition(1, p2_position);
//if (lrd.currentStartParticleID != lrd.previousStartParticleID || lrd.currentEndParticleID != lrd.previousEndParticleID)
//{
// lrd.timer = 0.0f;
//}
//if (lrd.timer < 1.0f)
//{
// lrd.timer += deltaTime / fadeInTime;
//}
//if (lrd.timer > 1.0f)
//{
// lrd.timer = 1.0f;
//}
float alphaAttenuation = alphaOverNormalizedDistance.Evaluate(distanceSqr / maxDistanceSqr);
//float alphaAttenuation = lrd.timer * alphaOverNormalizedDistance.Evaluate(distanceSqr / maxDistanceSqr);
lineStartColour.a = lineStartColourOriginalAlpha * alphaAttenuation;
lr.startColor = lineStartColour;
particleColour = particleColours[j];
Color lineEndColour = Color.LerpUnclamped(lineRendererEndColour, particleColour, colourFromParticle);
lineEndColour.a = Mathf.LerpUnclamped(lineRendererEndColour.a, particleColour.a, alphaFromParticle) * alphaAttenuation;
lr.endColor = lineEndColour;
lr.startWidth = lineStartWidth;
lr.endWidth = Mathf.LerpUnclamped(lineRendererEndWidth, particleSizes[j], widthFromParticle);
//lineRendererData[lrIndex] = lrd;
lrIndex++;
connections++;
// Intentionally taken AFTER connections++ (because index = 0 is the i'th / line origin particle).
connectedParticles[connections] = j;
if (connections == maxConnections || lrIndex == maxLineRenderers)
{
break;
}
}
}
if (connections >= 2)
{
connectedParticles[0] = i;
allConnectedParticles.Add(connectedParticles);
}
}
}
}
// Disable remaining line renderers from the pool that weren't used.
for (int i = lrIndex; i < lineRenderersCount; i++)
{
if (lineRenderers[i].enabled)
{
lineRenderers[i].enabled = false;
}
}
// I check against the filter rather than the mesh because the mesh should always exist as long as the filter reference is there.
// This way I can stop drawing/updating should the filter reference be lost.
if (trianglesMeshFilter)
{
// Triangles mesh.
// For efficiency (and my own general laziness), I only bother taking the first triangle formed.
// It doesn't matter all that much since this is an abstract effect anyway.
int vertexCount = allConnectedParticles.Count * 3;
Vector3[] vertices = new Vector3[vertexCount];
int[] triangles = new int[vertexCount];
Vector2[] uv = new Vector2[vertexCount];
Color[] colours = new Color[vertexCount];
float maxDistanceSqr = (maxDistance * maxDistance) * maxDistanceTriangleBias;
for (int i = 0; i < allConnectedParticles.Count; i++)
{
int[] connectedParticles = allConnectedParticles[i];
float distanceSqr = 0.0f;
if (trianglesDistanceCheck)
{
Vector3 particlePositionA = particlePositions[connectedParticles[1]];
Vector3 particlePositionB = particlePositions[connectedParticles[2]];
//distance = Vector3.Distance(particlePositionA, particlePositionB);
Vector3 difference;
difference.x = particlePositionA.x - particlePositionB.x;
difference.y = particlePositionA.y - particlePositionB.y;
difference.z = particlePositionA.z - particlePositionB.z;
distanceSqr =
difference.x * difference.x +
difference.y * difference.y +
difference.z * difference.z;
}
if (distanceSqr < maxDistanceSqr)
{
int i3 = i * 3;
vertices[i3 + 0] = particlePositions[connectedParticles[0]];
vertices[i3 + 1] = particlePositions[connectedParticles[1]];
vertices[i3 + 2] = particlePositions[connectedParticles[2]];
uv[i3 + 0] = new Vector2(0.0f, 0.0f);
uv[i3 + 1] = new Vector2(0.0f, 1.0f);
uv[i3 + 2] = new Vector2(1.0f, 1.0f);
triangles[i3 + 0] = i3 + 0;
triangles[i3 + 1] = i3 + 1;
triangles[i3 + 2] = i3 + 2;
colours[i3 + 0] = particleColours[connectedParticles[0]];
colours[i3 + 1] = particleColours[connectedParticles[1]];
colours[i3 + 2] = particleColours[connectedParticles[2]];
colours[i3 + 0] = Color.LerpUnclamped(Color.white, particleColours[connectedParticles[0]], triangleColourFromParticle);
colours[i3 + 1] = Color.LerpUnclamped(Color.white, particleColours[connectedParticles[1]], triangleColourFromParticle);
colours[i3 + 2] = Color.LerpUnclamped(Color.white, particleColours[connectedParticles[2]], triangleColourFromParticle);
colours[i3 + 0].a = Mathf.LerpUnclamped(1.0f, particleColours[connectedParticles[0]].a, triangleAlphaFromParticle);
colours[i3 + 1].a = Mathf.LerpUnclamped(1.0f, particleColours[connectedParticles[1]].a, triangleAlphaFromParticle);
colours[i3 + 2].a = Mathf.LerpUnclamped(1.0f, particleColours[connectedParticles[2]].a, triangleAlphaFromParticle);
}
}
trianglesMesh.Clear();
trianglesMesh.vertices = vertices;
trianglesMesh.uv = uv;
trianglesMesh.triangles = triangles;
trianglesMesh.colors = colours;
}
}
}
}
// =================================
// End functions.
// =================================
}
// =================================
// End namespace.
// =================================
}
}
}
// =================================
// --END-- //
// =================================

View File

@@ -0,0 +1,12 @@
fileFormatVersion: 2
guid: 75a5a8e349c9cf54496babb3e7fd5191
timeCreated: 1458196122
licenseType: Store
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,10 @@
fileFormatVersion: 2
guid: 76c3b696fa9b1e84b9b417fcbec52a51
folderAsset: yes
timeCreated: 1514855790
licenseType: Store
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.6 KiB

View File

@@ -0,0 +1,77 @@
fileFormatVersion: 2
guid: 1a0cb63a3bc8d2342852089bfb884192
timeCreated: 1514855896
licenseType: Store
TextureImporter:
fileIDToRecycleName: {}
externalObjects: {}
serializedVersion: 4
mipmaps:
mipMapMode: 0
enableMipMap: 1
sRGBTexture: 1
linearTexture: 0
fadeOut: 0
borderMipMap: 0
mipMapsPreserveCoverage: 0
alphaTestReferenceValue: 0.5
mipMapFadeDistanceStart: 1
mipMapFadeDistanceEnd: 3
bumpmap:
convertToNormalMap: 0
externalNormalMap: 0
heightScale: 0.25
normalMapFilter: 0
isReadable: 0
grayScaleToAlpha: 0
generateCubemap: 6
cubemapConvolution: 0
seamlessCubemap: 0
textureFormat: 1
maxTextureSize: 2048
textureSettings:
serializedVersion: 2
filterMode: -1
aniso: -1
mipBias: -1
wrapU: -1
wrapV: -1
wrapW: -1
nPOTScale: 1
lightmap: 0
compressionQuality: 50
spriteMode: 0
spriteExtrude: 1
spriteMeshType: 1
alignment: 0
spritePivot: {x: 0.5, y: 0.5}
spriteBorder: {x: 0, y: 0, z: 0, w: 0}
spritePixelsToUnits: 100
alphaUsage: 1
alphaIsTransparency: 0
spriteTessellationDetail: -1
textureType: 0
textureShape: 1
maxTextureSizeSet: 0
compressionQualitySet: 0
textureFormatSet: 0
platformSettings:
- buildTarget: DefaultTexturePlatform
maxTextureSize: 2048
resizeAlgorithm: 0
textureFormat: -1
textureCompression: 1
compressionQuality: 50
crunchedCompression: 0
allowsAlphaSplitting: 0
overridden: 0
androidETC2FallbackOverride: 0
spriteSheet:
serializedVersion: 2
sprites: []
outline: []
physicsShape: []
spritePackingTag:
userData:
assetBundleName:
assetBundleVariant:

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.8 KiB

View File

@@ -0,0 +1,77 @@
fileFormatVersion: 2
guid: fcc934170231d0244809002a4923c98b
timeCreated: 1514855896
licenseType: Store
TextureImporter:
fileIDToRecycleName: {}
externalObjects: {}
serializedVersion: 4
mipmaps:
mipMapMode: 0
enableMipMap: 1
sRGBTexture: 1
linearTexture: 0
fadeOut: 0
borderMipMap: 0
mipMapsPreserveCoverage: 0
alphaTestReferenceValue: 0.5
mipMapFadeDistanceStart: 1
mipMapFadeDistanceEnd: 3
bumpmap:
convertToNormalMap: 0
externalNormalMap: 0
heightScale: 0.25
normalMapFilter: 0
isReadable: 0
grayScaleToAlpha: 0
generateCubemap: 6
cubemapConvolution: 0
seamlessCubemap: 0
textureFormat: 1
maxTextureSize: 2048
textureSettings:
serializedVersion: 2
filterMode: -1
aniso: -1
mipBias: -1
wrapU: -1
wrapV: -1
wrapW: -1
nPOTScale: 1
lightmap: 0
compressionQuality: 50
spriteMode: 0
spriteExtrude: 1
spriteMeshType: 1
alignment: 0
spritePivot: {x: 0.5, y: 0.5}
spriteBorder: {x: 0, y: 0, z: 0, w: 0}
spritePixelsToUnits: 100
alphaUsage: 1
alphaIsTransparency: 0
spriteTessellationDetail: -1
textureType: 0
textureShape: 1
maxTextureSizeSet: 0
compressionQualitySet: 0
textureFormatSet: 0
platformSettings:
- buildTarget: DefaultTexturePlatform
maxTextureSize: 2048
resizeAlgorithm: 0
textureFormat: -1
textureCompression: 1
compressionQuality: 50
crunchedCompression: 0
allowsAlphaSplitting: 0
overridden: 0
androidETC2FallbackOverride: 0
spriteSheet:
serializedVersion: 2
sprites: []
outline: []
physicsShape: []
spritePackingTag:
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,9 @@
fileFormatVersion: 2
guid: 5431348cc70e26a4e9bbacb93a76cf2f
folderAsset: yes
timeCreated: 1472356639
licenseType: Store
DefaultImporter:
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,119 @@
// =================================
// Namespaces.
// =================================
using UnityEngine;
// =================================
// Define namespace.
// =================================
namespace MirzaBeig
{
namespace Scripting
{
namespace Effects
{
// =================================
// Classes.
// =================================
//[ExecuteInEditMode]
//[System.Serializable]
//[RequireComponent(typeof(ParticleSystem))]
static public class CreateLUT
{
// =================================
// Nested classes and structures.
// =================================
// ...
// =================================
// Variables.
// =================================
// ...
// =================================
// Functions.
// =================================
// ...
public static void fromGradient(int steps, Gradient gradient, ref Texture2D texture)
{
if (texture)
{
MonoBehaviour.Destroy(texture);
}
texture = new Texture2D(steps, 1);
// Assign the first and last beforehand.
// Min LUT width resolution is 2, so this will work without problems.
texture.SetPixel(0, 0, gradient.Evaluate(0.0f));
texture.SetPixel(steps - 1, 0, gradient.Evaluate(1.0f));
// Then fill the middle (if any -> meaning if resolution > 2).
for (int i = 1; i < steps - 1; i++)
{
Color colour = gradient.Evaluate(i / (float)steps);
texture.SetPixel(i, 0, colour);
}
texture.Apply();
}
public static void fromAnimationCurve(int steps, AnimationCurve curve, ref Texture2D texture)
{
if (texture)
{
MonoBehaviour.Destroy(texture);
}
texture = new Texture2D(steps, 1);
// Assign the first and last beforehand.
// Min LUT width resolution is 2, so this will work without problems.
texture.SetPixel(0, 0, new Color(0.0f, 0.0f, 0.0f, curve.Evaluate(0.0f)));
texture.SetPixel(steps - 1, 0, new Color(0.0f, 0.0f, 0.0f, curve.Evaluate(1.0f)));
// Then fill the middle (if any -> meaning if resolution > 2).
for (int i = 1; i < steps - 1; i++)
{
float value = curve.Evaluate(i / (float)steps);
texture.SetPixel(i, 0, new Color(0.0f, 0.0f, 0.0f, value));
}
texture.Apply();
}
// =================================
// End functions.
// =================================
}
// =================================
// End namespace.
// =================================
}
}
}
// =================================
// --END-- //
// =================================

View File

@@ -0,0 +1,12 @@
fileFormatVersion: 2
guid: 3c4c0dbe010be294facfeebdb24ccbb5
timeCreated: 1470567813
licenseType: Store
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant: