Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- using System;
- using System.Collections.Generic;
- using System.Diagnostics;
- using TMPro;
- using Unity.VisualScripting;
- using UnityEngine;
- using UnityEngine.Profiling;
- using UnityEngine.Serialization;
- using Debug = UnityEngine.Debug;
- using Random = UnityEngine.Random;
- public class Simulation : MonoBehaviour
- {
- public struct Particle
- {
- public Vector2 position, velocity;
- public float mass;
- }
- public int particleCount;
- public float radius;
- public float mass;
- public float timeScale;
- [Header("Quad Tree")]
- public float approximationThreshold;
- public int capacity;
- public int maxDepth;
- [Header("")]
- public bool centerAttraction;
- public float centerMass;
- public float particleForce;
- public Material material;
- Particle[] particles;
- QuadTree quadTree;
- new ParticleRenderer renderer;
- Particle center;
- TextMeshProUGUI latency;
- const int HalfScreenSize = 5;
- void Start()
- {
- center = new Particle
- {
- position = Vector2.zero,
- velocity = Vector2.zero,
- mass = centerMass
- };
- particles = new Particle[particleCount];
- for (int i = 0; i < particleCount; i++)
- {
- float posX = Random.Range(-HalfScreenSize + radius, HalfScreenSize - radius);
- float posY = Random.Range(-HalfScreenSize + radius, HalfScreenSize - radius);
- float centerDist = new Vector2(posX, posY).magnitude;
- float force = Mathf.Sqrt(centerMass / centerDist);
- Vector2 direction = new Vector2(posY, posX).normalized;
- Vector2 velocity = new Vector2(direction.x, -direction.y) * force * particleForce;
- particles[i] = new()
- {
- position = new Vector2(posX, posY),
- velocity = Vector2.zero,
- mass = mass
- };
- }
- latency = GameObject.Find("Latency").GetComponent<TextMeshProUGUI>();
- renderer = new(particles, material, radius);
- RebuildQuadTree();
- }
- void FixedUpdate()
- {
- Stopwatch watch = new();
- watch.Start();
- Profiler.BeginSample("UpdateVelocities");
- UpdateVelocities(Time.fixedDeltaTime * timeScale);
- Profiler.EndSample();
- Profiler.BeginSample("UpdatePositions");
- UpdatePositions(Time.fixedDeltaTime * timeScale);
- Profiler.EndSample();
- Profiler.BeginSample("RebuildQuadTree");
- RebuildQuadTree();
- Profiler.EndSample();
- watch.Stop();
- latency.text = watch.ElapsedMilliseconds + " ms";
- }
- void Update()
- {
- renderer.Render(particles);
- quadTree.DrawTree();
- }
- void OnDestroy()
- {
- renderer.ReleaseBuffers();
- }
- void UpdateVelocities(float timeStep)
- {
- for (int i = 0; i < particleCount; i++)
- {
- List<Particle> targets = quadTree.UpdateVelocity(particles[i], timeStep);
- Particle thisParticle = particles[i];
- int count = targets.Count;
- Debug.Log(targets.Count);
- for (int j = 0; j < count; j++)
- {
- thisParticle.velocity += CalculateAcceleration(thisParticle, targets[j]) * timeStep;
- }
- particles[i] = thisParticle;
- //particles[i] = quadTree.UpdateVelocity(particles[i], timeStep);
- }
- }
- Vector2 CalculateAcceleration(Particle p1, Particle p2)
- {
- Vector2 diff = p2.position - p1.position;
- Vector2 forceDir = diff.normalized;
- float sqrDst = Mathf.Max(diff.sqrMagnitude, 0.05f);
- Vector2 force = forceDir * (p1.mass * p2.mass) / sqrDst;
- Vector2 acceleration = force / p1.mass;
- return acceleration;
- }
- void UpdatePositions(float timeStep)
- {
- float minPosX = -HalfScreenSize + radius;
- float maxPosX = HalfScreenSize - radius;
- float minPosY = -HalfScreenSize + radius;
- float maxPosY = HalfScreenSize - radius;
- for (int i = 0; i < particleCount; i++)
- {
- Particle particle = particles[i];
- particle.position += particle.velocity * timeStep;
- Vector2 absPos = new(Mathf.Abs(particle.position.x), Mathf.Abs(particle.position.y));
- if (absPos.x < minPosX || absPos.x > maxPosX || absPos.y < minPosY || absPos.y > maxPosY)
- {
- float posX = Random.Range(minPosX, maxPosX);
- float posY = Random.Range(minPosY, maxPosY);
- particle.position = new Vector2(posX, posY);
- }
- particles[i] = particle;
- }
- }
- void RebuildQuadTree()
- {
- AABB boundary = new()
- {
- position = new Vector2(-5f, -5f),
- size = 10
- };
- quadTree = new(boundary);
- QuadTree.OverlapTolerance = radius;
- QuadTree.ApproximationThreshold = approximationThreshold;
- QuadTree.Capacity = capacity;
- QuadTree.MaxDepth = maxDepth;
- QuadTree.OriginalSize = HalfScreenSize * 2;
- for (int i = 0; i < particles.Length; i++)
- {
- quadTree.Insert(particles[i]);
- }
- quadTree.CalculateMassAndCenterOfMass();
- }
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement