Forum begins after the advertisement:
[Geneal] Creating Santa Water
Home › Forums › Video Game Tutorial Series › Creating a Rogue-like Shoot-em Up in Unity › [Geneal] Creating Santa Water
- This topic has 0 replies, 1 voice, and was last updated 2 weeks, 3 days ago by
Yip Si Yuan.
-
AuthorPosts
-
April 25, 2025 at 9:49 pm #18025::
Hi all! Recently, viewer Jukers asked for help in the forums with making a Santa Water Clone, so here’s a step-by-step guide on creating a basic Santa Water Weapon.
View post on imgur.com
Before we start, ensure that you’ve completed the series all the way up to Creating a Rogue-like (like Vampire Survivors) in Unity — Part 18: Implementing a Dynamic Stats System and UI, as we’ve made major improvements to it such as character stats affecting the weapon stats and much more.
Here’s what we will be covering.
- Creating the Santa Water Prerfabs
- Creating the SantaWaterWeapon.cs script
- Creating the SantaWater Weapon Data
- Creating the SantaWaterProjectile Script
1. Creating the Santa Water Prefabs
To start off, let’s create the Prefabs and VFX for our Santa Water weapon. There will be 2 Prefabs for the Santa Water it starts as a projectile and then spawns an aura after. 1.Create an empty GameObject in your scene and name it “Santa Water projectile”. Now Add a SpriteRenderer and set its layer to foreground. Then Drag in the sprite of your choice. 2.Add the projectile.cs script for now (we will be replacing it later with SantaWaterProjectile.cs), set the projectile script to autoaim and Damage Source to projectile. Next for the Rigidbody2D set it to Kinematic 3.Next Create another empty Gameobject and name it “Santa Water Aura”. now Add a particle system, SpriteRenderer, aura.cs script, circle collider2D and a Rigidbody(Kinematic). 4.For the settings in creating the VFX for the Santa Water First in the SpriteRenderer drag a circle icon and make it blue this will be the base of our aura. For the ParticleSystem here are the settings for the particles- Duration — 3
- Looping –true
- Prewarm –true
- Start color –42C4FF
- Start size — 1
- Start Speed –0 Emission
- Rate Over Time –50 Renderer
- Material — Default-Particle
View post on imgur.com
Afterwards Drag both GameObjects into your ProjectFolder to make it a Prefab
2. Creating Santa Water Script
Before Creating the Santa Water Script we would first need to update the
ProjectileWeapon.cs
script. Changes are highlight in the script.public class ProjectileWeapon : Weapon { protected float currentAttackInterval; protected int currentAttackCount; // Number of times this attack will happen. protected override void Update() { base.Update(); // Otherwise, if the attack interval goes from above 0 to below, we also call attack. if (currentAttackInterval > 0) { currentAttackInterval -= Time.deltaTime; if (currentAttackInterval <= 0) Attack(currentAttackCount); } } public override bool CanAttack() { if (currentAttackCount > 0) return true; return base.CanAttack(); } protected override bool Attack(int attackCount = 1) { // If no projectile prefab is assigned, leave a warning message. if (!currentStats.projectilePrefab) { Debug.LogWarning(string.Format("Projectile prefab has not been set for {0}", name)); ActivateCooldown(true); return false; } // Can we attack? if (!CanAttack()) return false; // Otherwise, calculate the angle and offset of our spawned projectile. float spawnAngle = GetSpawnAngle(); // If there is a proc effect, play it on the player. if (currentStats.procEffect) { Destroy(Instantiate(currentStats.procEffect, owner.transform), 5f); } // And spawn a copy of the projectile. Projectile prefab = Instantiate( currentStats.projectilePrefab, owner.transform.position + (Vector3)GetSpawnOffset(spawnAngle), Quaternion.Euler(0, 0, spawnAngle) ); prefab.weapon = this; prefab.owner = owner; OnProjectileSpawned(prefab); ActivateCooldown(true); attackCount--; // Do we perform another attack? if (attackCount > 0) { currentAttackCount = attackCount; currentAttackInterval = ((WeaponData)data).baseStats.projectileInterval; } return true; } protected virtual void OnProjectileSpawned(Projectile projectile) { } // Gets which direction the projectile should face when spawning. protected virtual float GetSpawnAngle() { return Mathf.Atan2(movement.lastMovedVector.y, movement.lastMovedVector.x) * Mathf.Rad2Deg; } // Generates a random point to spawn the projectile on, and // rotates the facing of the point by spawnAngle. protected virtual Vector2 GetSpawnOffset(float spawnAngle = 0) { return Quaternion.Euler(0, 0, spawnAngle) * new Vector2( Random.Range(currentStats.spawnVariance.xMin, currentStats.spawnVariance.xMax), Random.Range(currentStats.spawnVariance.yMin, currentStats.spawnVariance.yMax) ); } }
Here, we’ll set up the controller that will fire the projectiles. We’re going to create a new C# script called
SantaWaterWeapon.cs
. Here’s the script with an explanation further below:using System.Collections; using UnityEngine; // Custom weapon class for Santa's water projectile attack public class SantaWaterWeapon : ProjectileWeapon { // Triggered when a projectile is spawned; starts aura spawn coroutine protected override void OnProjectileSpawned(Projectile projectile) { if (projectile.owner == owner) { StartCoroutine(SpawnAuraAfterLifespan(projectile, 1.2f)); } } // Spawns an aura at the projectile's position after a delay, then destroys both public virtual IEnumerator SpawnAuraAfterLifespan(Projectile proj, float delay) { yield return new WaitForSeconds(delay); if (proj != null) { Vector2 pos = proj.transform.position; Aura aura = Instantiate(currentStats.auraPrefab, pos, Quaternion.identity); aura.weapon = this; aura.owner = owner; float trueArea = base.GetArea(); aura.transform.localScale = new Vector3(trueArea, trueArea, trueArea); Destroy(aura.gameObject, GetStats().lifespan); Destroy(proj.gameObject); } } // Override to prevent scaling of the bottle projectile public override float GetArea() { return 1; } // Calculates projectile spawn offset above the player’s position protected override Vector2 GetSpawnOffset(float spawnAngle = 0) { Vector2 playerPos = owner.transform.position; Vector2 topOfScreen = Camera.main.ViewportToWorldPoint(new Vector2(0.5f, 1f)); Vector2 spawnPos = new Vector2(playerPos.x, topOfScreen.y + 1f); return spawnPos - playerPos; } }
We are going to make it inherit from the ProjectileWeapon class, since it’s a weapon that uses Projectiles initially. This means we can override some functions to make the King Bible Work as intended.
The `OnProjectileSpawned()` function
This function will be called every time a projectile is spawned, it will then start a coroutine for that projectile spawned. which leads to the next function.
The `SpawnAuraAfterLifespan()` function
This function is responsible for spawning the aura after a set delay. A `yield return new WaitForSeconds` is used at the start to postpone the instantiation of the aura prefab.` Vector2 pos = proj.transform.position;` is used to store the postion of the projectile after the delay. The aura is then instantiated at that position using `Aura aura = Instantiate(currentStats.auraPrefab, pos, Quaternion.identity);` The reason we store the instantiate is so that we can easily reference it later in the script.After spawning the aura, both the projectile and the aura are scheduled for destruction. The line
Destroy(aura.gameObject, GetStats().lifespan);
delays the destruction of the aura by a specified duration. By passingGetStats().lifespan
as the delay parameter, the aura’s lifetime can scale based on the player’s stats and buffs.The `GetArea(`) function
In vampire survivors when for example u are to get a candelabrador which increase the size of your weapons. The santa water Bottle itself does not get scaled up but only the aura. which is why we have an `GetArea()` function that will at the start of the projectile life set its area back to 1Back in the SpawnAuraAfterLifespan() function we will then set the aura size to scale with the stats and buffs. By using the stored variable mentioned earlier we can reference the instanitated Aura by using
float trueArea = base.GetArea(); aura.transform.localScale = new Vector3(trueArea, trueArea, trueArea);
Now only the aura will increase in size while the bottle remains the same.
The `GetSpawnOffset()` function
This is the final function which is to offset the spawning of the projectiles. Typically the projectiles will be instantiated at the `transform.positon` of the player GameObject. But for the Santa Water it need to spawn from the top of the screen.Hence we would first get the players position ad store in a variable. We would then use
Vector2 topOfScreen = Camera.main.ViewportToWorldPoint(new Vector2(0.5f, 1f));
to get the position on top of the screen. Afterwards you would need to make a new variable to store the new position the projectile will be stored in.Afterwards
return spawnPos - playerPos;
. The reason why we – player position is because spawnPos is calculated as the position above the player — aligned with the player’s X, but positioned slightly off the top of the screen on the Y axis. But- playerPos
gives the direction and distance from the player to the spawn point.3. Creating the SantaWater Weapon Data
Next to Make a WeaponData for the santa Water, go into your project folder in your weapon Scriptable Objects/Weapons right-click > `Create > 2D Top-Down Rogue-like > WeaponData`. This will then create a new weapon data in the project folder. Rename it to “Santa Water” in Behavior click the drop down and choose SantaWaterWeapon . Then drag the SantaWater Prefab into the Projectile Prefab and SantaWaterAura Prefab in the aura Prefab.For the stats here’s the Santa Water Wikipage for it if you’d like to have the exact stats.
here is how my Santa Water Data is setup:
View post on imgur.com
4. 📌 Optional (but Recommended): SantaWaterProjectile Script
This part is entirely optional—Santa Water will function without it. However, this script ensures that the Santa Water projectile only lands within a fixed radius around the player, preventing it from going too far away.
using System.Collections; using System.Collections.Generic; using UnityEngine; // Handles behavior for a water projectile fired by Santa character public class SantaWaterProjectile : Projectile { public float maxDistanceFromPlayer = 5f; private Transform playerTransform; private Vector3 targetPosition; // Initialize projectile and get reference to player protected override void Start() { base.Start(); playerTransform = owner.transform; } // Update projectile behavior each physics frame protected override void FixedUpdate() { base.FixedUpdate(); // Restrict projectile within a max distance from the player float distanceFromPlayer = Vector3.Distance(transform.position, playerTransform.position); if (distanceFromPlayer > maxDistanceFromPlayer) { Vector3 direction = (transform.position - playerTransform.position).normalized; transform.position = playerTransform.position + direction * maxDistanceFromPlayer; } // Move projectile toward its target MoveTowardsTarget(); } // Moves the projectile toward its target position private void MoveTowardsTarget() { Vector3 directionToTarget = (targetPosition - transform.position).normalized; transform.position += directionToTarget * Time.deltaTime; if (Vector3.Distance(transform.position, targetPosition) < 0.1f) { transform.position = targetPosition; } } }
The `FixedUpdate()` and `start()` function
In the `Start()` function we would store the player Transform as the player by using `playerTransform = owner.transform;` which will be used later to help track the radius around the player. } In the `FixedUpdate()` function we are constanly checking if the projectile has exceeded the radius if it does it will correct its postion. else it will continue moving towards the target normally.The `MoveTowardsTargets()` function
This function essentially just moves the projectile to the targetpostitonReminder before testing
Remember to add the Santa Water Weapon Data into the “Available Weapons” section of the PlayerInventory, or else it won’t appear in the shop.As always, if you encounter any problems in creating the Santa Water weapon, you can submit a forum post about in detail for further assistance. If you have your own implementation of the Santa Water weapon, or have any improvements you’d want to see, feel free to make a post as well!
- 1 anonymous person
-
AuthorPosts
- You must be logged in to reply to this topic.
Advertisement below: