csharp 简单(未经优化!)粒子群。将它贴在带有ParticleSystem的GameObject上,并与检查员一起玩一些有趣的结果。 C

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了csharp 简单(未经优化!)粒子群。将它贴在带有ParticleSystem的GameObject上,并与检查员一起玩一些有趣的结果。 C相关的知识,希望对你有一定的参考价值。

using UnityEngine;
using System.Collections;
using System.Collections.Generic;


[RequireComponent( typeof( ParticleSystem ) )]
public class ParticleFlock : MonoBehaviour
{
	public Vector3 targetPosition;
	public int totalBoids = 15;

	[Range( 0.1f, 50f )]
	public float alignMaxDistance = 0.2f;
	[Range( 0.1f, 50f )]
	public float desiredSeperationDistance = 5f;
	[Range( 0.1f, 50f )]
	public float cohesionMaxDistance = 2f;
	[Range( 0.1f, 2f )]
	public float maxSpeed = 0.1f;
	[Range( 0.001f, 0.1f )]
	public float maxForce = 0.01f;

	[Range( 0.1f, 5f )]
	public float alignWeight = 1f;
	[Range( 0.1f, 5f )]
	public float seperationWeight = 3f;
	[Range( -10f, 3f )]
	public float cohesionWeight = 1f;
	[Range( 0.1f, 5f )]
	public float tendTowardPositionWeight = 1f;


	private ParticleSystem _particleSystem;
	private ParticleSystem.Particle[] _particles;


	void Awake()
	{
		_particleSystem = GetComponent<ParticleSystem>();

		// set our total boids. we limit the value entered in the inspector by the particleSystem max
		totalBoids = totalBoids > _particleSystem.maxParticles ? _particleSystem.maxParticles : totalBoids;
		_particleSystem.Emit( totalBoids );

		_particles = new ParticleSystem.Particle[_particleSystem.particleCount];
		_particleSystem.GetParticles( _particles );
	}


	void OnGUI()
	{
		if( GUILayout.Button( "Scatter" ) )
		{
			var tempCohesionWeight = cohesionWeight;
			var tempPositionWeight = tendTowardPositionWeight;

			cohesionWeight = -25f;
			tendTowardPositionWeight = 0.3f;

			StartCoroutine( resetSomeValueAfterDelay( 1.5f, () =>
			{
				cohesionWeight = tempCohesionWeight;
				tendTowardPositionWeight = tempPositionWeight;;
			} ) );
		}

		if( Event.current.isMouse && ( Event.current.type == EventType.MouseDown || Event.current.type == EventType.MouseDrag ) )
		{
			var mouse = new Vector3( Input.mousePosition.x, Input.mousePosition.y, 10f );
			targetPosition = Camera.main.ScreenToWorldPoint( mouse );
		}
	}


	IEnumerator resetSomeValueAfterDelay( float delay, System.Action action )
	{
		yield return new WaitForSeconds( delay );
		action();
	}



	void Update()
	{
		for( var i = 0; i < _particles.Length; i++ )
		{
			var acceleration = Vector3.zero;

			// acquire our forces and weight them
			var sep = separate( i ) * seperationWeight;
			var ali = align( i ) * alignWeight;
			var coh = cohesion( i ) * cohesionWeight;
			var tow = tendTowardLocation( i ) * tendTowardPositionWeight;

			// add to acceleration
			acceleration += sep;
			acceleration += ali;
			acceleration += coh;
			acceleration += tow;

			_particles[i].velocity += acceleration;

			// limit max velocity
			_particles[i].velocity = limitVectorMagnitude( _particles[i].velocity, maxSpeed );

			// move
			_particles[i].position += _particles[i].velocity;
		}

		_particleSystem.SetParticles( _particles, _particles.Length );
	}


	#region boid flocking

	Vector3 limitVectorMagnitude( Vector3 vec, float limit )
	{
		if( vec.magnitude > limit )
			return vec.normalized * limit;
		return vec;
	}


	private Vector3 seek( int boidIndex, Vector3 target )
	{
		var desired = target - _particles[boidIndex].position;  // A vector pointing from the location to the target

		// scale to maximum speed
		desired.Normalize();
		desired *= maxSpeed;

		// Steering = Desired minus Velocity
		var steer = desired - _particles[boidIndex].velocity;

		// limit our force
		if( steer.magnitude > maxForce )
			steer = steer.normalized * maxForce;

		return steer;
	}


	// check for nearby boids and steers away
	public Vector3 separate( int boidIndex )
	{
		var steer = Vector3.zero;
		var count = 0;

		for( var i = 0; i < _particles.Length; i++ )
		{
			if( i == boidIndex )
				continue;

			var d = Vector3.Distance( _particles[boidIndex].position, _particles[i].position );
			if( d < desiredSeperationDistance )
			{
				// calculate vector pointing away from neighbor
				var diff = _particles[boidIndex].position - _particles[i].position;
				diff.Normalize();
				diff /= d;
				steer += diff;
				count++; // keep track of how many we are avoiding
			}
		}

		// average -- divide by how many
		if( count > 0 )
			steer /= count;

		// As long as the vector is greater than 0
		if( steer.sqrMagnitude > 0 )
		{
			// Reynolds: Steering = Desired - Velocity
			steer.Normalize();
			steer *= maxSpeed;
			steer -= _particles[boidIndex].velocity;

			// limit our force
			steer = limitVectorMagnitude( steer, maxForce );
		}

		return steer;
	}


	// for every nearby boid in the system, calculate the average velocity
	public Vector3 align( int boidIndex )
	{
		var sum = Vector3.zero;
		int count = 0;

		for( var i = 0; i < _particles.Length; i++ )
		{
			if( i == boidIndex )
				continue;

			var d = Vector3.Distance( _particles[boidIndex].position, _particles[i].position );
			if( d < alignMaxDistance )
			{
				sum += _particles[i].velocity;
				count++;
			}
		}

		if( count > 0 )
		{
			sum /= count;

			// Reynolds: Steering = Desired - Velocity
			sum.Normalize();
			sum *= maxSpeed;
			var steer = sum - _particles[boidIndex].velocity;

			// limit our force
			return limitVectorMagnitude( steer, maxForce );
		}
		else
		{
			return Vector3.zero;
		}
	}


	// for the average location (i.e. center) of all nearby boids, calculate steering vector towards that location
	public Vector3 cohesion( int boidIndex )
	{
		var sum = Vector3.zero;   // Start with empty vector to accumulate all locations
		int count = 0;

		for( var i = 0; i < _particles.Length; i++ )
		{
			if( i == boidIndex )
				continue;

			var d = Vector3.Distance( _particles[boidIndex].position, _particles[i].position );
			if( d < cohesionMaxDistance )
			{
				sum += _particles[i].position;
				count++;
			}
		}

		if( count > 0 )
		{
			sum /= count;
			return seek( boidIndex, sum );  // Steer towards the location
		}

		return Vector3.zero;
	}


	Vector3 tendTowardLocation( int boidIndex )
	{
		return ( targetPosition - _particles[boidIndex].position ) * 0.02f;
	}

	#endregion

}

以上是关于csharp 简单(未经优化!)粒子群。将它贴在带有ParticleSystem的GameObject上,并与检查员一起玩一些有趣的结果。 C的主要内容,如果未能解决你的问题,请参考以下文章

粒子群优化算法的PSO

粒子群优化算法和多模态优化算法有啥区别

优化调度基于粒子群算法求解梯级水电站调度问题

粒子群优化算法(PSO)

优化求解混沌粒子群matlab源码

优化算法粒子群优化算法(PSO)含Matlab源码 1073期