<?xml version="1.0" encoding="UTF-8"?><rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>JustForFun &#8211; INCD021</title>
	<atom:link href="https://incd021.com/tag/justforfun/feed/" rel="self" type="application/rss+xml" />
	<link>https://incd021.com</link>
	<description>Programming, thoughts, life  and art.</description>
	<lastBuildDate>Wed, 19 Nov 2025 12:58:20 +0000</lastBuildDate>
	<language>en-US</language>
	<sy:updatePeriod>
	hourly	</sy:updatePeriod>
	<sy:updateFrequency>
	1	</sy:updateFrequency>
	<generator>https://wordpress.org/?v=6.8.3</generator>
	<item>
		<title>Simulator-driven Emergence</title>
		<link>https://incd021.com/2025/11/19/simulator-driven-emergence/</link>
					<comments>https://incd021.com/2025/11/19/simulator-driven-emergence/#respond</comments>
		
		<dc:creator><![CDATA[INC $D021]]></dc:creator>
		<pubDate>Wed, 19 Nov 2025 16:52:00 +0000</pubDate>
				<category><![CDATA[Programming]]></category>
		<category><![CDATA[Proof of concept]]></category>
		<category><![CDATA[Unity]]></category>
		<category><![CDATA[GeneratedArt]]></category>
		<category><![CDATA[JustForFun]]></category>
		<category><![CDATA[Learning]]></category>
		<category><![CDATA[POC]]></category>
		<guid isPermaLink="false">https://incd021.com/?p=878</guid>

					<description><![CDATA[Simulator.cs doesn’t drive the scene with hand-authored animation or fancy shaders. It spawns four families of particles, A, B, C, and D, and lets the math of their pairwise attraction/repulsion....]]></description>
										<content:encoded><![CDATA[
<p>Simulator.cs doesn’t drive the scene with hand-authored animation or fancy shaders. It spawns four families of particles, A, B, C, and D, and lets the math of their pairwise attraction/repulsion rules decide what the frame looks like. Every frame recomputes those forces, so the visible motion is the sum of tiny decisions instead of a scripted path.</p>



<h2 class="wp-block-heading">Particle families and setup</h2>



<p>Each family owns numberOfParticles lightweight Particle instances with positions, velocities, and a max speed limit. They spawn inside a circle and receive randomized velocities before Unity instantiates a prefab for each one. The simulator also generates a unique AnimationCurve plus [minDist, maxDist] for every ordered pair (A->B, B->C, etc.), so every run uses a fresh rule set.</p>



<div class="wp-block-kevinbatdorf-code-block-pro" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span style="display:flex;align-items:center;padding:10px 0px 10px 16px;margin-bottom:-2px;width:100%;text-align:left;background-color:#39404f;color:#c8d0e0">C#</span><span role="button" tabindex="0" style="color:#d8dee9ff;display:none" aria-label="Copy" class="code-block-pro-copy-button"><pre class="code-block-pro-copy-button-pre" aria-hidden="true"><textarea class="code-block-pro-copy-button-textarea" tabindex="-1" aria-hidden="true" readonly>void Start()
{
  // allocate particles/transforms per family
  ParticlesA = new Particle&#91;numberOfParticles&#93;;
  ParticlesB = new Particle&#91;numberOfParticles&#93;;
  ParticlesC = new Particle&#91;numberOfParticles&#93;;
  ParticlesD = new Particle&#91;numberOfParticles&#93;;
   TransformsA = new Transform&#91;numberOfParticles&#93;;
  TransformsB = new Transform&#91;numberOfParticles&#93;;
  TransformsC = new Transform&#91;numberOfParticles&#93;;
  TransformsD = new Transform&#91;numberOfParticles&#93;;
    // spawn each family with random position/velocity, then instantiate
  for (int j = 0; j &lt; numberOfParticles; j++)
  {
    ParticlesA&#91;j&#93; = new Particle(RandomPosition(), RandomVelosity(), VelosityMax);
    ParticlesB&#91;j&#93; = new Particle(RandomPosition(), RandomVelosity(), VelosityMax);
    ParticlesC&#91;j&#93; = new Particle(RandomPosition(), RandomVelosity(), VelosityMax);
    ParticlesD&#91;j&#93; = new Particle(RandomPosition(), RandomVelosity(), VelosityMax);
      TransformsA&#91;j&#93; = Instantiate(particlePrefabA, ParticlesA&#91;j&#93;.position, Quaternion.identity, null).transform;
    TransformsB&#91;j&#93; = Instantiate(particlePrefabB, ParticlesB&#91;j&#93;.position, Quaternion.identity, null).transform;
    TransformsC&#91;j&#93; = Instantiate(particlePrefabC, ParticlesC&#91;j&#93;.position, Quaternion.identity, null).transform;
    TransformsD&#91;j&#93; = Instantiate(particlePrefabD, ParticlesD&#91;j&#93;.position, Quaternion.identity, null).transform;
  }
}</textarea></pre><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2"></path></svg></span><pre class="shiki nord" style="background-color: #2e3440ff" tabindex="0"><code><span class="line"><span style="color: #81A1C1">void</span><span style="color: #D8DEE9FF"> </span><span style="color: #88C0D0">Start</span><span style="color: #ECEFF4">()</span></span>
<span class="line"><span style="color: #ECEFF4">{</span></span>
<span class="line"><span style="color: #ECEFF4">  </span><span style="color: #616E88">// allocate particles/transforms per family</span></span>
<span class="line"><span style="color: #D8DEE9FF">  </span><span style="color: #D8DEE9">ParticlesA</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">=</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">new</span><span style="color: #D8DEE9FF"> Particle</span><span style="color: #ECEFF4">&#91;</span><span style="color: #D8DEE9">numberOfParticles</span><span style="color: #ECEFF4">&#93;</span><span style="color: #81A1C1">;</span></span>
<span class="line"><span style="color: #D8DEE9FF">  </span><span style="color: #D8DEE9">ParticlesB</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">=</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">new</span><span style="color: #D8DEE9FF"> Particle</span><span style="color: #ECEFF4">&#91;</span><span style="color: #D8DEE9">numberOfParticles</span><span style="color: #ECEFF4">&#93;</span><span style="color: #81A1C1">;</span></span>
<span class="line"><span style="color: #D8DEE9FF">  </span><span style="color: #D8DEE9">ParticlesC</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">=</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">new</span><span style="color: #D8DEE9FF"> Particle</span><span style="color: #ECEFF4">&#91;</span><span style="color: #D8DEE9">numberOfParticles</span><span style="color: #ECEFF4">&#93;</span><span style="color: #81A1C1">;</span></span>
<span class="line"><span style="color: #D8DEE9FF">  </span><span style="color: #D8DEE9">ParticlesD</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">=</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">new</span><span style="color: #D8DEE9FF"> Particle</span><span style="color: #ECEFF4">&#91;</span><span style="color: #D8DEE9">numberOfParticles</span><span style="color: #ECEFF4">&#93;</span><span style="color: #81A1C1">;</span></span>
<span class="line"><span style="color: #D8DEE9FF">   </span><span style="color: #D8DEE9">TransformsA</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">=</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">new</span><span style="color: #D8DEE9FF"> Transform</span><span style="color: #ECEFF4">&#91;</span><span style="color: #D8DEE9">numberOfParticles</span><span style="color: #ECEFF4">&#93;</span><span style="color: #81A1C1">;</span></span>
<span class="line"><span style="color: #D8DEE9FF">  </span><span style="color: #D8DEE9">TransformsB</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">=</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">new</span><span style="color: #D8DEE9FF"> Transform</span><span style="color: #ECEFF4">&#91;</span><span style="color: #D8DEE9">numberOfParticles</span><span style="color: #ECEFF4">&#93;</span><span style="color: #81A1C1">;</span></span>
<span class="line"><span style="color: #D8DEE9FF">  </span><span style="color: #D8DEE9">TransformsC</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">=</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">new</span><span style="color: #D8DEE9FF"> Transform</span><span style="color: #ECEFF4">&#91;</span><span style="color: #D8DEE9">numberOfParticles</span><span style="color: #ECEFF4">&#93;</span><span style="color: #81A1C1">;</span></span>
<span class="line"><span style="color: #D8DEE9FF">  </span><span style="color: #D8DEE9">TransformsD</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">=</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">new</span><span style="color: #D8DEE9FF"> Transform</span><span style="color: #ECEFF4">&#91;</span><span style="color: #D8DEE9">numberOfParticles</span><span style="color: #ECEFF4">&#93;</span><span style="color: #81A1C1">;</span></span>
<span class="line"><span style="color: #ECEFF4">    </span><span style="color: #616E88">// spawn each family with random position/velocity, then instantiate</span></span>
<span class="line"><span style="color: #D8DEE9FF">  </span><span style="color: #81A1C1">for</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">(</span><span style="color: #81A1C1">int</span><span style="color: #D8DEE9FF"> j </span><span style="color: #81A1C1">=</span><span style="color: #D8DEE9FF"> </span><span style="color: #B48EAD">0</span><span style="color: #81A1C1">;</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">j</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">&lt;</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">numberOfParticles</span><span style="color: #81A1C1">;</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">j</span><span style="color: #81A1C1">++</span><span style="color: #ECEFF4">)</span></span>
<span class="line"><span style="color: #D8DEE9FF">  </span><span style="color: #ECEFF4">{</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #D8DEE9">ParticlesA</span><span style="color: #ECEFF4">&#91;</span><span style="color: #D8DEE9">j</span><span style="color: #ECEFF4">&#93;</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">=</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">new</span><span style="color: #D8DEE9FF"> Particle</span><span style="color: #ECEFF4">(</span><span style="color: #88C0D0">RandomPosition</span><span style="color: #ECEFF4">(),</span><span style="color: #D8DEE9FF"> </span><span style="color: #88C0D0">RandomVelosity</span><span style="color: #ECEFF4">(),</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">VelosityMax</span><span style="color: #ECEFF4">)</span><span style="color: #81A1C1">;</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #D8DEE9">ParticlesB</span><span style="color: #ECEFF4">&#91;</span><span style="color: #D8DEE9">j</span><span style="color: #ECEFF4">&#93;</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">=</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">new</span><span style="color: #D8DEE9FF"> Particle</span><span style="color: #ECEFF4">(</span><span style="color: #88C0D0">RandomPosition</span><span style="color: #ECEFF4">(),</span><span style="color: #D8DEE9FF"> </span><span style="color: #88C0D0">RandomVelosity</span><span style="color: #ECEFF4">(),</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">VelosityMax</span><span style="color: #ECEFF4">)</span><span style="color: #81A1C1">;</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #D8DEE9">ParticlesC</span><span style="color: #ECEFF4">&#91;</span><span style="color: #D8DEE9">j</span><span style="color: #ECEFF4">&#93;</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">=</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">new</span><span style="color: #D8DEE9FF"> Particle</span><span style="color: #ECEFF4">(</span><span style="color: #88C0D0">RandomPosition</span><span style="color: #ECEFF4">(),</span><span style="color: #D8DEE9FF"> </span><span style="color: #88C0D0">RandomVelosity</span><span style="color: #ECEFF4">(),</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">VelosityMax</span><span style="color: #ECEFF4">)</span><span style="color: #81A1C1">;</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #D8DEE9">ParticlesD</span><span style="color: #ECEFF4">&#91;</span><span style="color: #D8DEE9">j</span><span style="color: #ECEFF4">&#93;</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">=</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">new</span><span style="color: #D8DEE9FF"> Particle</span><span style="color: #ECEFF4">(</span><span style="color: #88C0D0">RandomPosition</span><span style="color: #ECEFF4">(),</span><span style="color: #D8DEE9FF"> </span><span style="color: #88C0D0">RandomVelosity</span><span style="color: #ECEFF4">(),</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">VelosityMax</span><span style="color: #ECEFF4">)</span><span style="color: #81A1C1">;</span></span>
<span class="line"><span style="color: #D8DEE9FF">      </span><span style="color: #D8DEE9">TransformsA</span><span style="color: #ECEFF4">&#91;</span><span style="color: #D8DEE9">j</span><span style="color: #ECEFF4">&#93;</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">=</span><span style="color: #D8DEE9FF"> </span><span style="color: #88C0D0">Instantiate</span><span style="color: #ECEFF4">(</span><span style="color: #D8DEE9">particlePrefabA</span><span style="color: #ECEFF4">,</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">ParticlesA</span><span style="color: #ECEFF4">&#91;</span><span style="color: #D8DEE9">j</span><span style="color: #ECEFF4">&#93;.</span><span style="color: #D8DEE9">position</span><span style="color: #ECEFF4">,</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">Quaternion</span><span style="color: #ECEFF4">.</span><span style="color: #D8DEE9">identity</span><span style="color: #ECEFF4">,</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">null</span><span style="color: #ECEFF4">).</span><span style="color: #D8DEE9">transform</span><span style="color: #81A1C1">;</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #D8DEE9">TransformsB</span><span style="color: #ECEFF4">&#91;</span><span style="color: #D8DEE9">j</span><span style="color: #ECEFF4">&#93;</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">=</span><span style="color: #D8DEE9FF"> </span><span style="color: #88C0D0">Instantiate</span><span style="color: #ECEFF4">(</span><span style="color: #D8DEE9">particlePrefabB</span><span style="color: #ECEFF4">,</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">ParticlesB</span><span style="color: #ECEFF4">&#91;</span><span style="color: #D8DEE9">j</span><span style="color: #ECEFF4">&#93;.</span><span style="color: #D8DEE9">position</span><span style="color: #ECEFF4">,</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">Quaternion</span><span style="color: #ECEFF4">.</span><span style="color: #D8DEE9">identity</span><span style="color: #ECEFF4">,</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">null</span><span style="color: #ECEFF4">).</span><span style="color: #D8DEE9">transform</span><span style="color: #81A1C1">;</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #D8DEE9">TransformsC</span><span style="color: #ECEFF4">&#91;</span><span style="color: #D8DEE9">j</span><span style="color: #ECEFF4">&#93;</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">=</span><span style="color: #D8DEE9FF"> </span><span style="color: #88C0D0">Instantiate</span><span style="color: #ECEFF4">(</span><span style="color: #D8DEE9">particlePrefabC</span><span style="color: #ECEFF4">,</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">ParticlesC</span><span style="color: #ECEFF4">&#91;</span><span style="color: #D8DEE9">j</span><span style="color: #ECEFF4">&#93;.</span><span style="color: #D8DEE9">position</span><span style="color: #ECEFF4">,</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">Quaternion</span><span style="color: #ECEFF4">.</span><span style="color: #D8DEE9">identity</span><span style="color: #ECEFF4">,</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">null</span><span style="color: #ECEFF4">).</span><span style="color: #D8DEE9">transform</span><span style="color: #81A1C1">;</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #D8DEE9">TransformsD</span><span style="color: #ECEFF4">&#91;</span><span style="color: #D8DEE9">j</span><span style="color: #ECEFF4">&#93;</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">=</span><span style="color: #D8DEE9FF"> </span><span style="color: #88C0D0">Instantiate</span><span style="color: #ECEFF4">(</span><span style="color: #D8DEE9">particlePrefabD</span><span style="color: #ECEFF4">,</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">ParticlesD</span><span style="color: #ECEFF4">&#91;</span><span style="color: #D8DEE9">j</span><span style="color: #ECEFF4">&#93;.</span><span style="color: #D8DEE9">position</span><span style="color: #ECEFF4">,</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">Quaternion</span><span style="color: #ECEFF4">.</span><span style="color: #D8DEE9">identity</span><span style="color: #ECEFF4">,</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">null</span><span style="color: #ECEFF4">).</span><span style="color: #D8DEE9">transform</span><span style="color: #81A1C1">;</span></span>
<span class="line"><span style="color: #D8DEE9FF">  </span><span style="color: #ECEFF4">}</span></span>
<span class="line"><span style="color: #ECEFF4">}</span></span></code></pre></div>



<h2 class="wp-block-heading"> How it works</h2>



<ul class="wp-block-list">
<li>Each frame recomputes the force on every particle by summing contributions from the other three families. GetForceA/GetForceB/… just call the shared CalculateForce helper with the corresponding SpatialGrid, Particle[], and InteractionConfig.</li>



<li>CalculateForce only visits nearby particles by hashing them into a grid whose cell size matches the longest interaction radius. It loops over neighboring cells up to cellRadius, so it never misses an influencer without scanning the whole population.</li>



<li>Only distances within [minDist², maxDist²] participate. The code normalizes the true distance to [0, 1] via (distance &#8211; minDist) / (maxDist &#8211; minDist) and samples the cached AnimationCurve, multiplying the scalar by forceScaler and the normalized displacement direction.</li>



<li>Every computed force is scaled by Time.deltaTime, passed to Particle.ApplyForce, and then the particle’s position is updated and bounded (the current Wrap is a no-op, so the bounds are more aspirational for now).</li>
</ul>



<div class="wp-block-kevinbatdorf-code-block-pro" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span style="display:flex;align-items:center;padding:10px 0px 10px 16px;margin-bottom:-2px;width:100%;text-align:left;background-color:#39404f;color:#c8d0e0">C#</span><span role="button" tabindex="0" style="color:#d8dee9ff;display:none" aria-label="Copy" class="code-block-pro-copy-button"><pre class="code-block-pro-copy-button-pre" aria-hidden="true"><textarea class="code-block-pro-copy-button-textarea" tabindex="-1" aria-hidden="true" readonly>Private Vector2 CalculateForce(Particle source, SpatialGrid grid, Particle[] targets, InteractionConfig config)
  if (source == null || grid == null || targets == null || config.maxDist &lt;= config.minDist)
    return Vector2.zero;
  
  grid.GetCell(source.position, out int x, out int y);
  Vector2 force = Vector2.zero;
  for (int offsetX = -config.cellRadius; offsetX &lt;= config.cellRadius; offsetX++)
  {
    for (int offsetY = -config.cellRadius; offsetY &lt;= config.cellRadius; offsetY++)
    {
      if (!grid.TryGetCell(x + offsetX, y + offsetY, out var cell))
      continue;
      foreach (int targetIndex in cell)
      {
        Vector2 displacement = source.position - targets&#91;targetIndex&#93;.position;
        float distanceSquared = displacement.sqrMagnitude;
        if (distanceSquared &lt; config.minDistSq || distanceSquared > config.maxDistSq)
          continue;
         float distance = Mathf.Sqrt(distanceSquared);
      if (distance &lt; 0.0001f)
        continue;
      float normalized = config.inverseRange > 0f ? (distance - config.minDist) * config.inverseRange : 0f;
      float curveValue = config.sampler.Evaluate(normalized);
      force += (displacement / distance) * (curveValue * forceScaler);
      }
    }
  }
    return force;
}</textarea></pre><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2"></path></svg></span><pre class="shiki nord" style="background-color: #2e3440ff" tabindex="0"><code><span class="line"><span style="color: #D8DEE9">Private</span><span style="color: #D8DEE9FF"> Vector2 </span><span style="color: #88C0D0">CalculateForce</span><span style="color: #ECEFF4">(</span><span style="color: #D8DEE9FF">Particle source</span><span style="color: #ECEFF4">,</span><span style="color: #D8DEE9FF"> SpatialGrid grid</span><span style="color: #ECEFF4">,</span><span style="color: #D8DEE9FF"> Particle</span><span style="color: #ECEFF4">[]</span><span style="color: #D8DEE9FF"> targets</span><span style="color: #ECEFF4">,</span><span style="color: #D8DEE9FF"> InteractionConfig config</span><span style="color: #ECEFF4">)</span></span>
<span class="line"><span style="color: #D8DEE9FF">  if </span><span style="color: #ECEFF4">(</span><span style="color: #D8DEE9FF">source == null || grid == null || targets == null || config.maxDist &lt;</span><span style="color: #81A1C1">=</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">config</span><span style="color: #ECEFF4">.</span><span style="color: #D8DEE9">minDist</span><span style="color: #ECEFF4">)</span></span>
<span class="line"><span style="color: #D8DEE9FF">    return Vector2.zero</span><span style="color: #81A1C1">;</span></span>
<span class="line"><span style="color: #D8DEE9FF">  </span></span>
<span class="line"><span style="color: #D8DEE9FF">  </span><span style="color: #D8DEE9">grid</span><span style="color: #ECEFF4">.</span><span style="color: #88C0D0">GetCell</span><span style="color: #ECEFF4">(</span><span style="color: #D8DEE9">source</span><span style="color: #ECEFF4">.</span><span style="color: #D8DEE9">position</span><span style="color: #ECEFF4">,</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">out</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">int</span><span style="color: #D8DEE9FF"> x</span><span style="color: #ECEFF4">,</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">out</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">int</span><span style="color: #D8DEE9FF"> y</span><span style="color: #ECEFF4">)</span><span style="color: #81A1C1">;</span></span>
<span class="line"><span style="color: #D8DEE9FF">  Vector2 force </span><span style="color: #81A1C1">=</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">Vector2</span><span style="color: #ECEFF4">.</span><span style="color: #D8DEE9">zero</span><span style="color: #81A1C1">;</span></span>
<span class="line"><span style="color: #D8DEE9FF">  </span><span style="color: #81A1C1">for</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">(</span><span style="color: #81A1C1">int</span><span style="color: #D8DEE9FF"> offsetX </span><span style="color: #81A1C1">=</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">-</span><span style="color: #D8DEE9">config</span><span style="color: #ECEFF4">.</span><span style="color: #D8DEE9">cellRadius</span><span style="color: #81A1C1">;</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">offsetX</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">&lt;=</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">config</span><span style="color: #ECEFF4">.</span><span style="color: #D8DEE9">cellRadius</span><span style="color: #81A1C1">;</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">offsetX</span><span style="color: #81A1C1">++</span><span style="color: #ECEFF4">)</span></span>
<span class="line"><span style="color: #D8DEE9FF">  </span><span style="color: #ECEFF4">{</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #81A1C1">for</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">(</span><span style="color: #81A1C1">int</span><span style="color: #D8DEE9FF"> offsetY </span><span style="color: #81A1C1">=</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">-</span><span style="color: #D8DEE9">config</span><span style="color: #ECEFF4">.</span><span style="color: #D8DEE9">cellRadius</span><span style="color: #81A1C1">;</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">offsetY</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">&lt;=</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">config</span><span style="color: #ECEFF4">.</span><span style="color: #D8DEE9">cellRadius</span><span style="color: #81A1C1">;</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">offsetY</span><span style="color: #81A1C1">++</span><span style="color: #ECEFF4">)</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #ECEFF4">{</span></span>
<span class="line"><span style="color: #D8DEE9FF">      </span><span style="color: #81A1C1">if</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">(</span><span style="color: #81A1C1">!</span><span style="color: #D8DEE9">grid</span><span style="color: #ECEFF4">.</span><span style="color: #88C0D0">TryGetCell</span><span style="color: #ECEFF4">(</span><span style="color: #D8DEE9">x</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">+</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">offsetX</span><span style="color: #ECEFF4">,</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">y</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">+</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">offsetY</span><span style="color: #ECEFF4">,</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">out</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">var</span><span style="color: #D8DEE9FF"> cell</span><span style="color: #ECEFF4">))</span></span>
<span class="line"><span style="color: #D8DEE9FF">      </span><span style="color: #81A1C1">continue;</span></span>
<span class="line"><span style="color: #D8DEE9FF">      </span><span style="color: #81A1C1">foreach</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">(</span><span style="color: #81A1C1">int</span><span style="color: #D8DEE9FF"> targetIndex </span><span style="color: #81A1C1">in</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">cell</span><span style="color: #ECEFF4">)</span></span>
<span class="line"><span style="color: #D8DEE9FF">      </span><span style="color: #ECEFF4">{</span></span>
<span class="line"><span style="color: #D8DEE9FF">        Vector2 displacement </span><span style="color: #81A1C1">=</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">source</span><span style="color: #ECEFF4">.</span><span style="color: #D8DEE9">position</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">-</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">targets</span><span style="color: #ECEFF4">&#91;</span><span style="color: #D8DEE9">targetIndex</span><span style="color: #ECEFF4">&#93;.</span><span style="color: #D8DEE9">position</span><span style="color: #81A1C1">;</span></span>
<span class="line"><span style="color: #D8DEE9FF">        </span><span style="color: #81A1C1">float</span><span style="color: #D8DEE9FF"> distanceSquared </span><span style="color: #81A1C1">=</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">displacement</span><span style="color: #ECEFF4">.</span><span style="color: #D8DEE9">sqrMagnitude</span><span style="color: #81A1C1">;</span></span>
<span class="line"><span style="color: #D8DEE9FF">        </span><span style="color: #81A1C1">if</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">(</span><span style="color: #D8DEE9">distanceSquared</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">&lt;</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">config</span><span style="color: #ECEFF4">.</span><span style="color: #D8DEE9">minDistSq</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">||</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">distanceSquared</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">&gt;</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">config</span><span style="color: #ECEFF4">.</span><span style="color: #D8DEE9">maxDistSq</span><span style="color: #ECEFF4">)</span></span>
<span class="line"><span style="color: #D8DEE9FF">          </span><span style="color: #81A1C1">continue;</span></span>
<span class="line"><span style="color: #D8DEE9FF">         </span><span style="color: #81A1C1">float</span><span style="color: #D8DEE9FF"> distance </span><span style="color: #81A1C1">=</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">Mathf</span><span style="color: #ECEFF4">.</span><span style="color: #88C0D0">Sqrt</span><span style="color: #ECEFF4">(</span><span style="color: #D8DEE9">distanceSquared</span><span style="color: #ECEFF4">)</span><span style="color: #81A1C1">;</span></span>
<span class="line"><span style="color: #D8DEE9FF">      </span><span style="color: #81A1C1">if</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">(</span><span style="color: #D8DEE9">distance</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">&lt;</span><span style="color: #D8DEE9FF"> </span><span style="color: #B48EAD">0.0001f</span><span style="color: #ECEFF4">)</span></span>
<span class="line"><span style="color: #D8DEE9FF">        </span><span style="color: #81A1C1">continue;</span></span>
<span class="line"><span style="color: #D8DEE9FF">      </span><span style="color: #81A1C1">float</span><span style="color: #D8DEE9FF"> normalized </span><span style="color: #81A1C1">=</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">config</span><span style="color: #ECEFF4">.</span><span style="color: #D8DEE9">inverseRange</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">&gt;</span><span style="color: #D8DEE9FF"> </span><span style="color: #B48EAD">0f</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">?</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">(</span><span style="color: #D8DEE9">distance</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">-</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">config</span><span style="color: #ECEFF4">.</span><span style="color: #D8DEE9">minDist</span><span style="color: #ECEFF4">)</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">*</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">config</span><span style="color: #ECEFF4">.</span><span style="color: #D8DEE9">inverseRange</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">:</span><span style="color: #D8DEE9FF"> </span><span style="color: #B48EAD">0f</span><span style="color: #81A1C1">;</span></span>
<span class="line"><span style="color: #D8DEE9FF">      </span><span style="color: #81A1C1">float</span><span style="color: #D8DEE9FF"> curveValue </span><span style="color: #81A1C1">=</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">config</span><span style="color: #ECEFF4">.</span><span style="color: #D8DEE9">sampler</span><span style="color: #ECEFF4">.</span><span style="color: #88C0D0">Evaluate</span><span style="color: #ECEFF4">(</span><span style="color: #D8DEE9">normalized</span><span style="color: #ECEFF4">)</span><span style="color: #81A1C1">;</span></span>
<span class="line"><span style="color: #D8DEE9FF">      </span><span style="color: #D8DEE9">force</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">+=</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">(</span><span style="color: #D8DEE9">displacement</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">/</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">distance</span><span style="color: #ECEFF4">)</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">*</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">(</span><span style="color: #D8DEE9">curveValue</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">*</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">forceScaler</span><span style="color: #ECEFF4">)</span><span style="color: #81A1C1">;</span></span>
<span class="line"><span style="color: #D8DEE9FF">      </span><span style="color: #ECEFF4">}</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #ECEFF4">}</span></span>
<span class="line"><span style="color: #D8DEE9FF">  </span><span style="color: #ECEFF4">}</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #81A1C1">return</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">force</span><span style="color: #81A1C1">;</span></span>
<span class="line"><span style="color: #D8DEE9FF">}</span></span></code></pre></div>



<h2 class="wp-block-heading"> Why you see those patterns</h2>



<figure class="wp-block-image size-full"><img fetchpriority="high" decoding="async" width="735" height="557" src="https://incd021.com/wp-content/uploads/2025/11/Artificial-Life-Screenshot-From-2025-11-18-21-12-32.png" alt="" class="wp-image-879" srcset="https://incd021.com/wp-content/uploads/2025/11/Artificial-Life-Screenshot-From-2025-11-18-21-12-32.png 735w, https://incd021.com/wp-content/uploads/2025/11/Artificial-Life-Screenshot-From-2025-11-18-21-12-32-300x227.png 300w" sizes="(max-width: 735px) 100vw, 735px" /></figure>



<p> Why you see those patterns<br>Every ordered pair (A->B, B->A, etc.) contributes a term to a coupled-looking differential system:<br>F₁ = Σ ((source − target).normalized × curve((|d| − min)/range) × forceScaler)<br> The direction comes from the normalized displacement, while the magnitude comes from whatever curve you provided, positive values attract, negative repel. Smooth curves produce soft clustering; sharp peaks trigger energetic oscillations and shells. Opposing curves create orbiting equilibria around their zero crossings. Because all curves and ranges are randomized on startup, the system behaves like a live experiment in emergent particle art every time.</p>



<h2 class="wp-block-heading">What to expect</h2>



<p>Visual output varies run-to-run, but common motifs are:</p>



<ul class="wp-block-list">
<li>Swirling filaments where one family chases another.</li>



<li>Drifting, layered shells where attraction balances repulsion.</li>



<li>Momentary clumps that form, burst, and reform as the curves fluctuate.</li>
</ul>



<p>The damping parameter keeps the kinetic energy in check, and the spatial grid keeps the update loop fast even with thousands of particles.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://incd021.com/2025/11/19/simulator-driven-emergence/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
	</channel>
</rss>

<!--
Page Caching using Disk: Enhanced 

Served from: incd021.com @ 2025-11-20 04:38:05 by W3 Total Cache
-->