using UnityEngine; using System.Collections.Generic; using System.Collections; public class Atom : MonoBehaviour { public string elementName; public string elementSymbol; public int atomicNumber; public float atomicWeight; public int protonCount; public Color protonColor; public int neutronCount; public Color neutronColor; public int[] electronConfiguration; public float electronShellSpacing = 0.5f; public Color electronColor; public bool spinElectrons = true; public bool freezeNucleusMovementAfter5Seconds = true; List shells = new List(); Transform nucleus; private float electronFirstShellSpacing; public void Start() { electronFirstShellSpacing = 0.26f; //Assign Nucleus GameObject nucleus = transform.GetChild(0); //Nucleons int pc = protonCount; int nc = neutronCount; float scaleCount = 0.2f; generateProton(transform.position); pc -= 1; for (int i = 1; i <= nc + pc; i++) { int nucleonsToCreate = int.Parse((Mathf.Pow(2f, i - 1f) * 5f).ToString()); if (nc + pc >= nucleonsToCreate) { string s = createNucleons(nucleonsToCreate, scaleCount, pc, nc); scaleCount += 0.2f; pc -= int.Parse(s.Split(',')[0]); nc -= int.Parse(s.Split(',')[1]); } else { string s = createNucleons(pc + nc, scaleCount, pc, nc); scaleCount += 0.2f; pc -= int.Parse(s.Split(',')[0]); nc -= int.Parse(s.Split(',')[1]); } } //Electrons GameObject[] shellsGO = generateElectronShells(); for (int loop = 0; loop < electronConfiguration.Length; loop++) { int numPoints = electronConfiguration[loop]; for (int pointNum = 0; pointNum < numPoints; pointNum++) { float i = (float)(pointNum * 1.0) / numPoints; float angle = i * Mathf.PI * 2; float x = transform.position.x + (Mathf.Sin(angle) * (3 * (loop + 1))); float z = transform.position.z + (Mathf.Cos(angle) * (3 * (loop + 1))); Vector3 pos = new Vector3(x, transform.position.y, z); generateElectron(pos, electronFirstShellSpacing + (electronShellSpacing * loop), loop + 1, shellsGO[loop]); atomicNumber += 1; } } } string createNucleons(int nPoints, float scale, int pcount, int ncount) { int npc = 0; int nnc = 0; float fPoints = (float)nPoints; Vector3[] points = new Vector3[nPoints]; float inc = Mathf.PI * (3 - Mathf.Sqrt(5)); float off = 2 / fPoints; for (int k = 0; k < nPoints; k++) { float y = k * off - 1 + (off / 2); float r = Mathf.Sqrt(1 - y * y); float phi = k * inc; points[k] = new Vector3(Mathf.Cos(phi) * r, y, Mathf.Sin(phi) * r); } foreach (Vector3 point in points) { if (pcount > 0 && ncount > 0) { int borc = Random.Range(1, 10); if (borc > 5 && pcount > 0) { GameObject outerSphere = generateProton(transform.position); outerSphere.transform.position += point * scale; npc += 1; pcount -= 1; } else if (borc < 6 && ncount > 0) { GameObject outerSphere = generateNeutron(transform.position); outerSphere.transform.position += point * scale; nnc += 1; ncount -= 1; } } else if (pcount > 0 && ncount == 0) { GameObject outerSphere = generateProton(transform.position); outerSphere.transform.position += point * scale; npc += 1; pcount -= 1; } else if (pcount == 0 && ncount > 0) { GameObject outerSphere = generateNeutron(transform.position); outerSphere.transform.position += point * scale; nnc += 1; ncount -= 1; } } return npc + "," + nnc; } public void AddParticel(string particle) { int nc = 0; int pc = 0; Debug.Log("Adding " + particle); if (particle == "electron") { AddElectron(); } else { if (particle == "proton") pc = 1; else if (particle == "neutron") nc = 1; float scaleCount = 0.2f; for (int i = 1; i <= nc + pc; i++) { int nucleonsToCreate = int.Parse((Mathf.Pow(2f, i - 1f) * 5f).ToString()); if (nc + pc >= nucleonsToCreate) { string s = createNucleons(nucleonsToCreate, scaleCount, pc, nc); scaleCount += 0.2f; pc -= int.Parse(s.Split(',')[0]); nc -= int.Parse(s.Split(',')[1]); } else { string s = createNucleons(pc + nc, scaleCount, pc, nc); scaleCount += 0.2f; pc -= int.Parse(s.Split(',')[0]); nc -= int.Parse(s.Split(',')[1]); } } } } private void AddElectron() { foreach (GameObject shell in shells) { Destroy(shell); } shells.Clear(); if (IsShellFull(electronConfiguration.Length, electronConfiguration[electronConfiguration.Length - 1])) { int[] newConfig = new int[electronConfiguration.Length + 1]; for (int i = 0; i < electronConfiguration.Length; i++) { newConfig[i] = electronConfiguration[i]; } newConfig[electronConfiguration.Length] = 1; electronConfiguration = newConfig; Debug.Log("Shell full -- New electron configuration: " + newConfig); } else { electronConfiguration[electronConfiguration.Length - 1]++; } GameObject[] shellsGO = generateElectronShells(); for (int loop = 0; loop < electronConfiguration.Length; loop++) { int numPoints = electronConfiguration[loop]; for (int pointNum = 0; pointNum < numPoints; pointNum++) { float i = (float)(pointNum * 1.0) / numPoints; float angle = i * Mathf.PI * 2; float x = transform.position.x + (Mathf.Sin(angle) * (3 * (loop + 1))); float z = transform.position.z + (Mathf.Cos(angle) * (3 * (loop + 1))); Vector3 pos = new Vector3(x, transform.position.y, z); generateElectron(pos, electronFirstShellSpacing + (electronShellSpacing * loop), loop + 1, shellsGO[loop]); atomicNumber += 1; } } } bool IsShellFull(int shellNumber, int numElectrons) { // Calculate the maximum capacity of the given shell int maxCapacity = 2 * shellNumber * shellNumber; // Compare the number of electrons with the maximum capacity return numElectrons == maxCapacity; } bool prevSpinElectrons = true; public void Update() { Vector3 currentRotation = transform.eulerAngles; float clampedYRotation = Mathf.Clamp(currentRotation.y, -90f, 90f); transform.eulerAngles = new Vector3(-45f, clampedYRotation, currentRotation.z); if (spinElectrons && !prevSpinElectrons) { foreach (GameObject e in FindObjectsOfType(typeof(GameObject))) { if (e.name == "Electron") { e.GetComponent().enabled = true; prevSpinElectrons = spinElectrons; } } } else if (!spinElectrons && prevSpinElectrons) { foreach (GameObject e in FindObjectsOfType(typeof(GameObject))) { if (e.name == "Electron") { e.GetComponent().enabled = false; prevSpinElectrons = spinElectrons; } } } } public void drawCircle(float radius, LineRenderer lr) { lr.positionCount = 361; lr.useWorldSpace = false; lr.startWidth = lr.endWidth = 0.01f; lr.materials[0] = new Material(Shader.Find("Diffuse")); lr.materials[0].SetColor("_Color", new Color32(128, 223, 255, 0)); float x, y = 0, z, angle = 0; for (int i = 0; i < 361; i++) { x = Mathf.Sin(Mathf.Deg2Rad * angle) * radius; z = Mathf.Cos(Mathf.Deg2Rad * angle) * radius; lr.SetPosition(i, new Vector3(x, y, z)); angle += 1; } } public GameObject generateProton(Vector3 pos) { GameObject proton = GameObject.CreatePrimitive(PrimitiveType.Sphere); proton.name = "Proton"; proton.transform.position = pos; proton.AddComponent().useGravity = false; Renderer renderer = proton.GetComponent(); Material material = new Material(Shader.Find("Universal Render Pipeline/Lit")); material.color = protonColor; renderer.material = material; proton.AddComponent(); proton.transform.SetParent(nucleus); proton.transform.localScale = new Vector3(0.25f, 0.25f, 0.25f); return proton; } public GameObject generateNeutron(Vector3 pos) { GameObject neutron = GameObject.CreatePrimitive(PrimitiveType.Sphere); neutron.name = "Neutron"; neutron.transform.position = pos; neutron.AddComponent().useGravity = false; Renderer renderer = neutron.GetComponent(); Material material = new Material(Shader.Find("Universal Render Pipeline/Lit")); material.color = neutronColor; renderer.material = material; neutron.GetComponent().material.SetColor("_Color", neutronColor); neutron.AddComponent(); neutron.transform.SetParent(nucleus); neutron.transform.localScale = new Vector3(0.25f, 0.25f, 0.25f); return neutron; } public GameObject[] generateElectronShells() { for (int loop = 0; loop < electronConfiguration.Length; loop++) { GameObject shell = new GameObject(); shell.name = "Shell " + (loop + 1); shell.transform.parent = transform; shell.transform.localPosition = nucleus.localPosition; LineRenderer lr = shell.AddComponent(); drawCircle(electronFirstShellSpacing + (electronShellSpacing * loop), lr); shells.Add(shell); } return shells.ToArray(); } public void generateElectron(Vector3 pos, float r, int shell, GameObject shellGO) { GameObject electron = GameObject.CreatePrimitive(PrimitiveType.Sphere); electron.name = "Electron"; electron.transform.localScale = new Vector3(0.08f, 0.08f, 0.08f); electron.transform.position = pos; electron.transform.parent = shellGO.transform; Renderer renderer = electron.GetComponent(); Material material = new Material(Shader.Find("Universal Render Pipeline/Lit")); material.color = electronColor; renderer.material = material; Destroy(electron.GetComponent()); Electron e = electron.AddComponent(); e.radius = r; e.centre = transform; e.rotationSpeed = 80 + (10 * shell); } public Vector3 getNucleusPosition() { return transform.position; } public Vector3 getShellPosition() { if (IsShellFull(electronConfiguration.Length, electronConfiguration[electronConfiguration.Length - 1])) { float x = transform.position.x + (Mathf.Sin(0) * (3 * (electronConfiguration.Length + 1))); float z = transform.position.z + (Mathf.Cos(0) * (3 * (electronConfiguration.Length + 1))); Vector3 result = new Vector3(x, transform.position.y, z); float radius = electronFirstShellSpacing + (electronShellSpacing * (electronConfiguration.Length)); return (result - transform.position).normalized * radius + transform.position; } else { float x = transform.position.x + (Mathf.Sin(0) * (3 * (electronConfiguration.Length))); float z = transform.position.z + (Mathf.Cos(0) * (3 * (electronConfiguration.Length))); Vector3 result = new Vector3(x, transform.position.y, z); float radius = electronFirstShellSpacing + (electronShellSpacing * (electronConfiguration.Length)); float radius2 = electronFirstShellSpacing + (electronShellSpacing * (electronConfiguration.Length - 1)); Debug.Log("Radius1 = " + radius + "; Radius2 = " + radius2); return (result - transform.position).normalized * radius + transform.position; } } }