At first I wasn't really proud of this one, but then I decided that I need to know what's so bad about it? Why does it feel unsatisfying? How can I do it better?
So yeah here's a unity project that does the following:
Spawns a maximum of 3 wall bouncing corona balls where the player clicks, which when they collide with each other they heal some health, and if with a wall (screen edges) they loose health. I also tried to do so their alpha value changes in proportion with its health (the closer it is to the death, the more transparent it is). There is a text showing how many time the corona balls bounced of the walls. One last thing, it plays a cough sound on collision.
Here are the scripts I have and which gameObject are they attached to:
Basic script I found online, I remember reading and understanding it before writing on my own, can't recall if I modified it though. Its attached to the camera obviously:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
// script to instantiate edge colliders at start
public class edges : MonoBehaviour
{
public PhysicsMaterial2D bouncy;
void Awake()
{
AddCollider();
}
void AddCollider()
{
if (Camera.main == null) { Debug.LogError("Camera.main not found, failed to create edge colliders"); return; }
var cam = Camera.main;
if (!cam.orthographic) { Debug.LogError("Camera.main is not Orthographic, failed to create edge colliders"); return; }
var bottomLeft = (Vector2)cam.ScreenToWorldPoint(new Vector3(0, 0, cam.nearClipPlane));
var topLeft = (Vector2)cam.ScreenToWorldPoint(new Vector3(0, cam.pixelHeight, cam.nearClipPlane));
var topRight = (Vector2)cam.ScreenToWorldPoint(new Vector3(cam.pixelWidth, cam.pixelHeight, cam.nearClipPlane));
var bottomRight = (Vector2)cam.ScreenToWorldPoint(new Vector3(cam.pixelWidth, 0, cam.nearClipPlane));
// add or use existing EdgeCollider2D
var edge = GetComponent<EdgeCollider2D>() == null ? gameObject.AddComponent<EdgeCollider2D>() : GetComponent<EdgeCollider2D>();
var edgePoints = new[] { bottomLeft, topLeft, topRight, bottomRight, bottomLeft };
edge.points = edgePoints;
edge.sharedMaterial = bouncy;
}
}
Script attached to HUD (canvas), it just has a AddBounce method to display bounce count, would be surprised if I screwed even this:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
// Script for HUD management, and stuf...
public class HUD : MonoBehaviour
{
// declaring them fields
[SerializeField]
Text bounceText;
int bounces;
// Start is called before the first frame update
void Start()
{
// assign number of bounces to text
bounceText.text = bounces.ToString();
}
// Method to add bounces
public void AddBounce()
{
bounces += 1;
bounceText.text = bounces.ToString();
}
}
This is the spawner attached to the camera that detects players clicks so it can spawn coronas as long as there aren't 3 or more already:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class coronaSpawner : MonoBehaviour
{
// declaring fields
[SerializeField]
GameObject prefabCorona;
// Start is called before the first frame update
void Start()
{
}
// Update is called once per frame
void Update()
{
if (Input.GetButtonDown("Fire1"))
{
if (GameObject.FindGameObjectsWithTag("corona").Length < 3)
{
// gets mouse location and convert it to world position
Vector3 mouseLocation = Input.mousePosition;
Vector3 worldPosition = Camera.main.ScreenToWorldPoint(mouseLocation);
worldPosition.z = 2f;
// spawns a corona in mouse location
Instantiate(prefabCorona, worldPosition, Quaternion.identity);
}
}
}
}
And finally, here's what I hate (I think?), a blunder of horribly declared fields that feel that are too much already, here's the script attached to the coronaPrefab which traces its health, alphaValue, X and Y values for impulse force and everything else you'll have to figure out reading it:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class bouncer : MonoBehaviour
{
//declaring variables
[SerializeField]
int health = 100;
[SerializeField]
int minX = 6;
[SerializeField]
int maxX = 9;
[SerializeField]
int minY = 4;
[SerializeField]
int maxY = 20;
[SerializeField]
int fragility = 10;
float fullHealth;
float alphaValue;
HUD hud;
AudioSource audioSource;
// Start is called before the first frame update
void Start()
{
// assigning fields
audioSource = GetComponent<AudioSource>();
fullHealth = health;
// calculates right alpha value for the sprite to dissapear at death
alphaValue = (float)1 / (health / fragility);
// taking RigidBody2D and adding random impulse force
Rigidbody2D rb2d = GetComponent<Rigidbody2D>();
rb2d.AddForce(new Vector2(Random.Range(minX,maxX), Random.Range(minY,maxY)), ForceMode2D.Impulse);
// taking HUD component
hud = GameObject.FindGameObjectWithTag("HUD").GetComponent<HUD>();
}
// called when the Object's colider enters a collision with another collider
void OnCollisionEnter2D(Collision2D col)
{
// calls the Change method
audioSource.Play();
Change(col);
}
// gets alpha value, changes it and assigns it back. Also reduces or adds health
private void Change(Collision2D col)
{
// gets color componenent
Color color = GetComponent<SpriteRenderer>().color;
// adds or reduce values depending on choice
if (col.gameObject.tag == "MainCamera")
{
hud.AddBounce();
health -= fragility;
if (health <= 0)
{
Destroy(gameObject);
}
}
else if (col.gameObject.tag == "corona")
{
health += fragility * 2;
Range(health, 0, fullHealth * 1.5);
}
// assigns color component back with modified alpha value
color.a = health / fullHealth;
GetComponent<SpriteRenderer>().color = color;
}
// makes sure value is within a reasonable range
public static double Range(int value, double minimum, double maximum)
{
if (value < minimum) { return minimum; }
if (value > maximum) { return maximum; }
return value;
}
}
So yeah, this is one of my training Unity Projects, I'll be forever grateful to you if you give it a look and tell me what I could've done better, and thank you in advance!
Also I would like a smoll tip, when I get feedback on a script(s?), should I go back and change what I can? Should I try to test all the new features and tricks I learned in a different project? Or should I just read, understand and memorize? Again, thank you all so much that for your help and for taking the time and effort to share your experiences so us beginners can learn! ^^